17. 电话号码的字母组合
自己的答案:
自己写的时候,多次用到了String的拼接,很耗时间,对StringBuffer不熟悉,并且对回溯也不太熟悉
class Solution {
public List<String> letterCombinations(String digits) {
List<String> list = new ArrayList();
if(digits==null||digits.length()==0) {
return list;
}
Map<Integer,char[]> map =new HashMap();
map.put(2,new char[]{'a','b','c'});
map.put(3,new char[]{'d','e','f'});
map.put(4,new char[]{'g','h','i'});
map.put(5,new char[]{'j','k','l'});
map.put(6,new char[]{'m','n','o'});
map.put(7,new char[]{'q','p','r','s'});
map.put(8,new char[]{'t','u','v'});
map.put(9,new char[]{'w','x','y','z'});
char[] ch = map.get(digits.charAt(0)-'0');
for(int i = 0; i < ch.length;i++) {
list.add(new String(ch[i]+""));
}
for(int i = 1 ; i < digits.length();i++) {
ch = map.get(digits.charAt(i)-'0');
List<String> listTemp = new ArrayList();
for(int j = 0; j < list.size();j++){
String s = list.get(j);
for(int k = 0; k < ch.length;k++) {
listTemp.add(s+ch[k]);
}
}
list.clear();
list.addAll(listTemp);
}
// list.stream().forEach(System.out::println);
return list;
}
}
人家的代码:
我做的时候没有弄清楚buffer里的东西使用完以后该怎么删除. 没有掌握回溯的精髓
class Solution {
public List<String> letterCombinations(String digits) {
List<String> list = new ArrayList();
if(digits==null||digits.length()==0) {
return list;
}
Map<Integer,char[]> map =new HashMap();
map.put(2,new char[]{'a','b','c'});
map.put(3,new char[]{'d','e','f'});
map.put(4,new char[]{'g','h','i'});
map.put(5,new char[]{'j','k','l'});
map.put(6,new char[]{'m','n','o'});
map.put(7,new char[]{'q','p','r','s'});
map.put(8,new char[]{'t','u','v'});
map.put(9,new char[]{'w','x','y','z'});
letter(list,digits,map,0,new StringBuffer());
return list;
}
public void letter(List<String> list,String digits,Map<Integer,char[]> map ,
int index,StringBuffer buffer) {
if(digits.length()==index) {
list.add(buffer.toString());
return;
}
char[] ch = map.get(digits.charAt(index)-'0');
for(int i = 0 ; i < ch.length;i++) {
buffer.append(ch[i]);
letter(list,digits,map,index+1,buffer); // 做的时候没有弄清楚buffer里的东西使用完以后该怎么删除. 没有掌握回溯的精髓
buffer.deleteCharAt(index);
}
}
}
22. 括号生成
数字 n
代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
自己写的:
代码写的很啰嗦,而且会有重复的,用了一个hashmap来判断
class Solution {
List<String>[] resList = new ArrayList[9];
public List<String> generateParenthesis(int n) {
if(resList[n]!=null)
return resList[n];
List<String> list = new ArrayList();
if(n==1){
list.add("()");
resList[1] =list;
return list;
}
Set<String> set = new HashSet<>();
List<String> L = generateParenthesis(n-1);
for(String s:L) {
String s1 = "("+s+")";
list.add(s1);
set.add(s1);
}
for(int i = 1 ; i < n;i++) {
List<String> L1 = generateParenthesis(i);
List<String> L2 = generateParenthesis(n-i);
for(String s1:L1) {
for(String s2:L2){
String s = s1+s2;
if(set.add(s))
list.add(s1+s2);
}
}
}
resList[n] = list;
return list;
}
}
回溯版本的答案
每次添加一个(
或者一个)
(
的数目>)
的数目才添加)
class Solution {
List<String>[] resList = new ArrayList[9];
public List<String> generateParenthesis(int n) {
List<String> list = new ArrayList();
generate(list,new StringBuffer(),0,0,0,n);
return list;
}
public void generate(List<String> list,StringBuffer buffer,
int open,int close,int index,int max) {
if(index == max*2){
list.add(buffer.toString());
return;
}
if(open<max) {
buffer.append('(');
generate(list,buffer,open+1,close,index+1,max);
buffer.deleteCharAt(index);
}
if(close<open) {
buffer.append(')');
generate(list,buffer,open,close+1,index+1,max);
buffer.deleteCharAt(index);
}
}
}
答案版本的自己写的
class Solution {
ArrayList[] cache = new ArrayList[100];
public List<String> generate(int n) {
if (cache[n] != null) {
return cache[n];
}
ArrayList<String> ans = new ArrayList<String>();
if (n == 0) {
ans.add("");
} else {
for (int c = 0; c < n; ++c) {
for (String left: generate(c)) {
for (String right: generate(n - 1 - c)) {
ans.add("(" + left + ")" + right);
}
}
}
}
cache[n] = ans;
return ans;
}
public List<String> generateParenthesis(int n) {
return generate(n);
}
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/generate-parentheses/solution/gua-hao-sheng-cheng-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
47. 全排列 II
很好的题目!
对于[1,1,1,1,2,3,4,4,5]来说,要保证重复的数字的放置顺序是有序的。
class Solution {
int n = 0;
List<List<Integer>> result = new ArrayList();
List<Integer> list = new ArrayList();
boolean[] flag = null;
public List<List<Integer>> permuteUnique(int[] nums) {
n = nums.length;
if(n==0){
return result;
}
flag = new boolean[n];
Arrays.sort(nums);
dfs(nums,0);
return result;
}
public void dfs(int[] nums,int idx) {
if(idx==n){
result.add(new ArrayList(list));
return;
}
for(int i = 0; i < n;i++) {
// 这个命令就是规定使重复的元素相对有序
if(flag[i] || i >= 1 && nums[i] == nums[i-1] && !flag[i-1])
continue;
flag[i] = !flag[i];
list.add(nums[i]);
dfs(nums,idx+1);
list.remove(idx);
flag[i] = !flag[i];
}
}
}
子集
78. 子集
回溯 ```java class Solution { int length = 0; List
- > result = new ArrayList();
boolean[] flag = null;
List
list = new ArrayList(); public List
- > subsets(int[] nums) {
length = nums.length;
result.add(new ArrayList());
if(length==0)
return result;
for(int i = 1; i <= length;i++) {
dfs(nums,i,0,0); // 每次选择i长度的元素
}
return result;
}
void dfs(int[] nums,int size,int numSize,int start) {
if(size==numSize) {
result.add(new ArrayList(list));
return;
}
for(int i = start ; i < length;i++) {
list.add(nums[i]);
dfs(nums,size,numSize+1,i+1);
list.remove(numSize);
}
}
}
2. 位运算
```java
class Solution {
public List<List<Integer>> subsets(int[] nums) {
int length = nums.length;
int num = (1<<length)-1;
List<List<Integer>> result = new ArrayList();
result.add(new ArrayList());
List<Integer> list = new ArrayList();
for(int i = 1; i <= num;i++) {
int j = i;
int len = 0;
while(len<length) {
if((j&(1<<len))!=0) {
list.add(nums[len]);
}
len++;
}
result.add(new ArrayList(list));
list.clear();
}
return result;
}
}
90. 子集 II
对于1,2,2,3,4,4,4:
1:0个1,一个1两种情况
2:0个、1个、2个 三种情况
3:0、1 两种
4:0、1、2、3 四种
共有:232*4=48
class Solution {
List<List<Integer>> result = new ArrayList();
List<Integer> list = new ArrayList();
int n =0;
public List<List<Integer>> subsetsWithDup(int[] nums) {
n = nums.length;
Arrays.sort(nums);
dfs(nums,0);
return result;
}
void dfs(int[] nums,int idx) {
if(idx==n){
result.add(new ArrayList(list));
return;
}
int k =0; //重复元素的个数
while(idx+k<n && nums[idx+k]==nums[idx]) k++;
for(int i = 0 ; i <= k;i++) {
// ==k的目的是为了使当前元素的最后一个重复元素可以在最后一步加入res中
dfs(nums,idx+k);
list.add(nums[idx]);
}
for(int i = 0 ; i <= k;i++) {
list.remove(list.size()-1);
}
}
}
473. 火柴拼正方形
剪枝的题目
https://www.acwing.com/solution/content/3785/
class Solution {
int length;
int has = 0;
long size=0;
boolean[] flag;
List<Integer> nums;
public boolean makesquare(int[] s) {
length = s.length;
long all = 0;
for(int n:s) {
all+=n;
}
if(length==0||all%4!=0)
return false;
size = all/4;
flag = new boolean[length];
nums = Arrays.stream(s).boxed().collect(Collectors.toList());
Collections.sort(nums,Collections.reverseOrder());
return dfs(0,0);
}
boolean dfs(int u,int cur) {
if(cur == size) {
u++;cur=0;
}
if(u==4) // u==4一定已经完成了,而且已经到达了最末尾,因为nums的总和=4*size
{return true;}
for(int i = 0 ;i < length;i++) {
if(!flag[i] && cur+nums.get(i)<=size) {
flag[i] = true;
if(dfs(u,cur+nums.get(i))) {
return true;
}
flag[i] = false;
if(i==0) return false;
while(i+1<length && nums.get(i+1)==nums.get(i)) i++;
}
}
return false;
}
}