401. 二进制手表
二进制手表顶部有 4 个 LED 代表 小时(0-11),底部的 6 个 LED 代表 分钟(0-59)。每个 LED 代表一个 0 或 1,最低位在右侧。
给你一个整数 turnedOn ,表示当前亮着的 LED 的数量,返回二进制手表可以表示的所有可能时间。你可以 按任意顺序 返回答案。
小时不会以零开头:
例如,“01:00” 是无效的时间,正确的写法应该是 “1:00” 。
分钟必须由两位数组成,可能会以零开头:
例如,“10:2” 是无效的时间,正确的写法应该是 “10:02” 。
思路
遍历0-11和0-59,求二进制1的和即可
完整代码
public List<String> readBinaryWatch(int turnedOn) {
//第一排0-11。除了第二个灯,其余的灯可以同时亮
//第二排0-59,除了第3个灯,其余的灯可以同时亮
//java中Integer.bitCount()可以计算得到
List<String> ans = new ArrayList<>();
for(int i = 0; i < 12; i++){
for(int j = 0; j < 60; j++){
if(Integer.bitCount(i) + Integer.bitCount(j) == turnedOn){
String str = String.valueOf(i) + ":";
if(j < 10){
str += ("0" + String.valueOf(j));
}else{
str += String.valueOf(j);
}
ans.add(str);
}
}
}
return ans;
}
剑指 Offer 38. 字符串的排列
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
思路
打印排列,但是不能有重复的元素,一开始以为是排列中的组成元素是唯一的,但真正含义应该是,最后的排列中不应该有重复的组合
- 在使用回溯的过程中,我们会画出树形结构,观察不难发现,如果我们要得到不一样的组合,那么,在同一层的结点中,我们不应该取到相同的节点。所以,当遇到有相同节点的时候,应该跳过。
- 那么我们怎么知道什么节点被遍历过了?用标记数组记录即可
完整代码
public String[] permutation(String s) {
StringBuffer sb = new StringBuffer();
List<String> ans = new ArrayList<>();
int[] visited = new int[s.length()];
char[] ch = s.toCharArray();
Arrays.sort(ch);
backtrack(ch, 0, sb, ans, visited);
String[] res = new String[ans.size()];
for(int i = 0; i < ans.size(); i++){
res[i] = ans.get(i);
}
return res;
}
public static void backtrack(char[] ch, int index, StringBuffer sb, List<String> ans, int[] visited){
if(index == ch.length){
ans.add(sb.toString());
return;
}
for(int i = 0; i < ch.length; i++){
//去重,同一层节点中排在前面的相同结点被标记过了就跳过
if(i > 0 && ch[i] == ch[i - 1] && visited[i - 1] != 1){
continue;
}
//如果没有被标记过
if(visited[i] != 1){
visited[i] = 1;
sb.append(ch[i]);
backtrack(ch, index + 1, sb, ans, visited);
sb.deleteCharAt(sb.length() - 1);
visited[i] = 0;
}
}
}