贪心算法——点灯问题

简介: 贪心算法——点灯问题

题目

给定一个字符串str,只由‘X’和‘.’两种字符构成。‘X’表示墙,不能放灯,也不需要点亮。‘.’表示居民点,可以放灯,需要点亮。如果灯放在i位置,可以让i-1, i和i+1三个位置被点亮。返回如果点亮str中所有需要点亮的位置,至少需要几盏灯。image.png

package com.harrison.class09;
import java.util.HashSet;
public class Code03_Light {
  // 方法一:贪心
  public static int minLight1(String road) {
    char[] str = road.toCharArray();
    int index = 0;
    int lights = 0;
    while (index < str.length) {// 一旦越界,说明都已经决定好了,返回最少的灯数
      if (str[index] == 'X') {// i位置是X,直接去i++做决定
        index++;
      } else {// i位置是点 分情况讨论
        lights++;
        if (index + 1 == str.length) {// 不需要放灯了
          break;
        }
        if (str[index + 1] == 'X') {// i+1位置是X,必须在i位置放灯,然后去i+2位置做决定
          index = index + 2;
        } else {// i+1位置是. 不管i+2位置是X还是. 都在i+1位置放灯,然后去i+3位置做决定
          index = index + 3;
        }
      }
    }
    return lights;
  }
  // str[index....]位置,自由选择放灯还是不放灯
  // str[0..index-1]位置呢?已经做完决定了,那些放了灯的位置,存在lights里
  // 要求选出能照亮所有.的方案,并且在这些有效的方案中,返回最少需要几个灯
  public static int process2(char[] str, int index, HashSet<Integer> lights) {
    if (index == str.length) {// 结束的时候
      for (int i = 0; i < str.length; i++) {
        if (str[i] != 'X') {// 如果当前位置是点的话
          if (!lights.contains(i - 1) && !lights.contains(i) && !lights.contains(i + 1)) {
            return Integer.MAX_VALUE;
          }
        }
      }
      return lights.size();
    } else {
      // str还没结束
      // i位置无论是'X'还是'.',都有一个选择,那就是不放灯
      // no 当前i位置没有放灯,返回后续的最好灯数
      int no = process2(str, index + 1, lights);
      int yes = Integer.MAX_VALUE;// yes 只有'.'才会变
      if (str[index] == '.') {
        lights.add(index);
        yes = process2(str, index + 1, lights);
        lights.remove(index);
      }
      return Math.min(no, yes);
    }
  }
  // 方法二:暴力解
  public static int minLight2(String road) {
    if (road == null || road.length() == 0) {
      return 0;
    }
    return process2(road.toCharArray(), 0, new HashSet<>());
  }
  public static String generateRandomString(int len) {
    char[] ans = new char[(int) (Math.random() * (len + 1))];
    for (int i = 0; i < ans.length; i++) {
      ans[i] = Math.random() < 0.5 ? 'X' : '.';
    }
    return String.valueOf(ans);
  }
  public static void main(String[] args) {
    int len = 20;
    int testTime = 100000;
    for (int i = 0; i < testTime; i++) {
      String test = generateRandomString(len);
      int ans1 = minLight1(test);
      int ans2 = minLight2(test);
      if (ans1 != ans2) {
        System.out.println("oops!");
      }
    }
    System.out.println("finish!");
  }
}
相关文章
宝藏例题(欧几里得算法+素数的三种境界………)
宝藏例题(欧几里得算法+素数的三种境界………)
宝藏例题(欧几里得算法+素数的三种境界………)
|
存储 算法
每日一题,贪心算法的简单应用
每日一题,贪心算法的简单应用
|
9月前
|
容器
每日一题——接雨水(单调栈)
每日一题——接雨水(单调栈)
|
算法 数据可视化 机器人
用遗传算法寻找迷宫出路
遗传算法是一种基于达尔文进化论的搜索启发式算法。该算法模拟了基于种群中最适合个体的自然选择。
430 0
用遗传算法寻找迷宫出路
|
算法 C++
蓝桥杯(聪明的猴子)克鲁斯卡尔算法最小生成树
蓝桥杯(聪明的猴子)克鲁斯卡尔算法最小生成树
127 0
|
存储 算法 JavaScript
双指针解决【接雨水】问题
本篇将带来双指针算法经典题目之:接雨水问题;
|
算法 前端开发 图计算
力扣-接雨水-你没看过的解法 ! 非动态规划 ! 近100%
力扣-接雨水-你没看过的解法 ! 非动态规划 ! 近100%
122 0
|
缓存 算法 网络协议
贪心法
贪心法是把一个复杂问题分解为一系列较为简单的局部最优选择,每一步选择都是对当前解的一个扩展,直到获得问题的完整解。贪心法的典型应用是求解最优化问题,而且对许多问题都能得到整体最优解,即使不能得到整体最优解,通常也是最优解的很好近似。
|
存储
【贪心法】程序存储问题
【贪心法】程序存储问题
251 0

热门文章

最新文章