17. 电话号码的字母组合

image.png
自己的答案:
自己写的时候,多次用到了String的拼接,很耗时间,对StringBuffer不熟悉,并且对回溯也不太熟悉

  1. class Solution {
  2. public List<String> letterCombinations(String digits) {
  3. List<String> list = new ArrayList();
  4. if(digits==null||digits.length()==0) {
  5. return list;
  6. }
  7. Map<Integer,char[]> map =new HashMap();
  8. map.put(2,new char[]{'a','b','c'});
  9. map.put(3,new char[]{'d','e','f'});
  10. map.put(4,new char[]{'g','h','i'});
  11. map.put(5,new char[]{'j','k','l'});
  12. map.put(6,new char[]{'m','n','o'});
  13. map.put(7,new char[]{'q','p','r','s'});
  14. map.put(8,new char[]{'t','u','v'});
  15. map.put(9,new char[]{'w','x','y','z'});
  16. char[] ch = map.get(digits.charAt(0)-'0');
  17. for(int i = 0; i < ch.length;i++) {
  18. list.add(new String(ch[i]+""));
  19. }
  20. for(int i = 1 ; i < digits.length();i++) {
  21. ch = map.get(digits.charAt(i)-'0');
  22. List<String> listTemp = new ArrayList();
  23. for(int j = 0; j < list.size();j++){
  24. String s = list.get(j);
  25. for(int k = 0; k < ch.length;k++) {
  26. listTemp.add(s+ch[k]);
  27. }
  28. }
  29. list.clear();
  30. list.addAll(listTemp);
  31. }
  32. // list.stream().forEach(System.out::println);
  33. return list;
  34. }
  35. }

人家的代码:
我做的时候没有弄清楚buffer里的东西使用完以后该怎么删除. 没有掌握回溯的精髓

  1. class Solution {
  2. public List<String> letterCombinations(String digits) {
  3. List<String> list = new ArrayList();
  4. if(digits==null||digits.length()==0) {
  5. return list;
  6. }
  7. Map<Integer,char[]> map =new HashMap();
  8. map.put(2,new char[]{'a','b','c'});
  9. map.put(3,new char[]{'d','e','f'});
  10. map.put(4,new char[]{'g','h','i'});
  11. map.put(5,new char[]{'j','k','l'});
  12. map.put(6,new char[]{'m','n','o'});
  13. map.put(7,new char[]{'q','p','r','s'});
  14. map.put(8,new char[]{'t','u','v'});
  15. map.put(9,new char[]{'w','x','y','z'});
  16. letter(list,digits,map,0,new StringBuffer());
  17. return list;
  18. }
  19. public void letter(List<String> list,String digits,Map<Integer,char[]> map ,
  20. int index,StringBuffer buffer) {
  21. if(digits.length()==index) {
  22. list.add(buffer.toString());
  23. return;
  24. }
  25. char[] ch = map.get(digits.charAt(index)-'0');
  26. for(int i = 0 ; i < ch.length;i++) {
  27. buffer.append(ch[i]);
  28. letter(list,digits,map,index+1,buffer); // 做的时候没有弄清楚buffer里的东西使用完以后该怎么删除. 没有掌握回溯的精髓
  29. buffer.deleteCharAt(index);
  30. }
  31. }
  32. }

22. 括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
image.png
自己写的:
代码写的很啰嗦,而且会有重复的,用了一个hashmap来判断

  1. class Solution {
  2. List<String>[] resList = new ArrayList[9];
  3. public List<String> generateParenthesis(int n) {
  4. if(resList[n]!=null)
  5. return resList[n];
  6. List<String> list = new ArrayList();
  7. if(n==1){
  8. list.add("()");
  9. resList[1] =list;
  10. return list;
  11. }
  12. Set<String> set = new HashSet<>();
  13. List<String> L = generateParenthesis(n-1);
  14. for(String s:L) {
  15. String s1 = "("+s+")";
  16. list.add(s1);
  17. set.add(s1);
  18. }
  19. for(int i = 1 ; i < n;i++) {
  20. List<String> L1 = generateParenthesis(i);
  21. List<String> L2 = generateParenthesis(n-i);
  22. for(String s1:L1) {
  23. for(String s2:L2){
  24. String s = s1+s2;
  25. if(set.add(s))
  26. list.add(s1+s2);
  27. }
  28. }
  29. }
  30. resList[n] = list;
  31. return list;
  32. }
  33. }

回溯版本的答案

每次添加一个(或者一个)
(的数目>)的数目才添加)

  1. class Solution {
  2. List<String>[] resList = new ArrayList[9];
  3. public List<String> generateParenthesis(int n) {
  4. List<String> list = new ArrayList();
  5. generate(list,new StringBuffer(),0,0,0,n);
  6. return list;
  7. }
  8. public void generate(List<String> list,StringBuffer buffer,
  9. int open,int close,int index,int max) {
  10. if(index == max*2){
  11. list.add(buffer.toString());
  12. return;
  13. }
  14. if(open<max) {
  15. buffer.append('(');
  16. generate(list,buffer,open+1,close,index+1,max);
  17. buffer.deleteCharAt(index);
  18. }
  19. if(close<open) {
  20. buffer.append(')');
  21. generate(list,buffer,open,close+1,index+1,max);
  22. buffer.deleteCharAt(index);
  23. }
  24. }
  25. }

答案版本的自己写的

  1. class Solution {
  2. ArrayList[] cache = new ArrayList[100];
  3. public List<String> generate(int n) {
  4. if (cache[n] != null) {
  5. return cache[n];
  6. }
  7. ArrayList<String> ans = new ArrayList<String>();
  8. if (n == 0) {
  9. ans.add("");
  10. } else {
  11. for (int c = 0; c < n; ++c) {
  12. for (String left: generate(c)) {
  13. for (String right: generate(n - 1 - c)) {
  14. ans.add("(" + left + ")" + right);
  15. }
  16. }
  17. }
  18. }
  19. cache[n] = ans;
  20. return ans;
  21. }
  22. public List<String> generateParenthesis(int n) {
  23. return generate(n);
  24. }
  25. }
  26. 作者:LeetCode-Solution
  27. 链接:https://leetcode-cn.com/problems/generate-parentheses/solution/gua-hao-sheng-cheng-by-leetcode-solution/
  28. 来源:力扣(LeetCode
  29. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

47. 全排列 II

很好的题目!
image.png
对于[1,1,1,1,2,3,4,4,5]来说,要保证重复的数字的放置顺序是有序的。

  1. class Solution {
  2. int n = 0;
  3. List<List<Integer>> result = new ArrayList();
  4. List<Integer> list = new ArrayList();
  5. boolean[] flag = null;
  6. public List<List<Integer>> permuteUnique(int[] nums) {
  7. n = nums.length;
  8. if(n==0){
  9. return result;
  10. }
  11. flag = new boolean[n];
  12. Arrays.sort(nums);
  13. dfs(nums,0);
  14. return result;
  15. }
  16. public void dfs(int[] nums,int idx) {
  17. if(idx==n){
  18. result.add(new ArrayList(list));
  19. return;
  20. }
  21. for(int i = 0; i < n;i++) {
  22. // 这个命令就是规定使重复的元素相对有序
  23. if(flag[i] || i >= 1 && nums[i] == nums[i-1] && !flag[i-1])
  24. continue;
  25. flag[i] = !flag[i];
  26. list.add(nums[i]);
  27. dfs(nums,idx+1);
  28. list.remove(idx);
  29. flag[i] = !flag[i];
  30. }
  31. }
  32. }

子集

78. 子集

image.png

  1. 回溯 ```java class Solution { int length = 0; List> result = new ArrayList(); boolean[] flag = null; List list = new ArrayList();

    public List> subsets(int[] nums) {

    1. length = nums.length;
    2. result.add(new ArrayList());
    3. if(length==0)
    4. return result;
    5. for(int i = 1; i <= length;i++) {
    6. dfs(nums,i,0,0); // 每次选择i长度的元素
    7. }
    8. return result;

    }

    void dfs(int[] nums,int size,int numSize,int start) {

    1. if(size==numSize) {
    2. result.add(new ArrayList(list));
    3. return;
    4. }
    5. for(int i = start ; i < length;i++) {
    6. list.add(nums[i]);
    7. dfs(nums,size,numSize+1,i+1);
    8. list.remove(numSize);
    9. }

    }

}

  1. 2. 位运算
  2. ```java
  3. class Solution {
  4. public List<List<Integer>> subsets(int[] nums) {
  5. int length = nums.length;
  6. int num = (1<<length)-1;
  7. List<List<Integer>> result = new ArrayList();
  8. result.add(new ArrayList());
  9. List<Integer> list = new ArrayList();
  10. for(int i = 1; i <= num;i++) {
  11. int j = i;
  12. int len = 0;
  13. while(len<length) {
  14. if((j&(1<<len))!=0) {
  15. list.add(nums[len]);
  16. }
  17. len++;
  18. }
  19. result.add(new ArrayList(list));
  20. list.clear();
  21. }
  22. return result;
  23. }
  24. }

90. 子集 II

image.png
对于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

  1. class Solution {
  2. List<List<Integer>> result = new ArrayList();
  3. List<Integer> list = new ArrayList();
  4. int n =0;
  5. public List<List<Integer>> subsetsWithDup(int[] nums) {
  6. n = nums.length;
  7. Arrays.sort(nums);
  8. dfs(nums,0);
  9. return result;
  10. }
  11. void dfs(int[] nums,int idx) {
  12. if(idx==n){
  13. result.add(new ArrayList(list));
  14. return;
  15. }
  16. int k =0; //重复元素的个数
  17. while(idx+k<n && nums[idx+k]==nums[idx]) k++;
  18. for(int i = 0 ; i <= k;i++) {
  19. // ==k的目的是为了使当前元素的最后一个重复元素可以在最后一步加入res中
  20. dfs(nums,idx+k);
  21. list.add(nums[idx]);
  22. }
  23. for(int i = 0 ; i <= k;i++) {
  24. list.remove(list.size()-1);
  25. }
  26. }
  27. }

473. 火柴拼正方形

剪枝的题目
https://www.acwing.com/solution/content/3785/
image.png
image.png

  1. class Solution {
  2. int length;
  3. int has = 0;
  4. long size=0;
  5. boolean[] flag;
  6. List<Integer> nums;
  7. public boolean makesquare(int[] s) {
  8. length = s.length;
  9. long all = 0;
  10. for(int n:s) {
  11. all+=n;
  12. }
  13. if(length==0||all%4!=0)
  14. return false;
  15. size = all/4;
  16. flag = new boolean[length];
  17. nums = Arrays.stream(s).boxed().collect(Collectors.toList());
  18. Collections.sort(nums,Collections.reverseOrder());
  19. return dfs(0,0);
  20. }
  21. boolean dfs(int u,int cur) {
  22. if(cur == size) {
  23. u++;cur=0;
  24. }
  25. if(u==4) // u==4一定已经完成了,而且已经到达了最末尾,因为nums的总和=4*size
  26. {return true;}
  27. for(int i = 0 ;i < length;i++) {
  28. if(!flag[i] && cur+nums.get(i)<=size) {
  29. flag[i] = true;
  30. if(dfs(u,cur+nums.get(i))) {
  31. return true;
  32. }
  33. flag[i] = false;
  34. if(i==0) return false;
  35. while(i+1<length && nums.get(i+1)==nums.get(i)) i++;
  36. }
  37. }
  38. return false;
  39. }
  40. }