九章算法_九章算法(杭州)科技有限公司

九章算法_九章算法(杭州)科技有限公司1BST迭代器注意点:1.实际就是中序遍历的非递归写法,迭代器就是要用Stack存储数据,不过把不同的模块功能进行了分割,而不是一次完成中序遍历;2.可以把添加到Stack单独抽取成一个函数

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

1  BST迭代器

注意点:1. 实际就是中序遍历的非递归写法,迭代器就是要用Stack存储数据,不过把不同的模块功能进行了分割,而不是一次完成中序遍历;

    2. 可以把添加到Stack单独抽取成一个函数,面向对象,更容易理解。

http://www.lintcode.com/en/problem/binary-search-tree-iterator/#

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  public class BSTIterator {
 2     //@param root: The root of binary tree.
 3     TreeNode next = null;
 4     Stack<TreeNode> stack = new Stack<TreeNode>();
 5     public BSTIterator(TreeNode root) {
 6         // write your code here
 7         next = root;
 8     }
 9 
10     //@return: True if there has next node, or false
11     public boolean hasNext() {
12         // write your code here
13         while(next != null) {
14             stack.push(next);
15             next = next.left;
16         }
17         if(stack.isEmpty()) return false;
18         return true;
19     }
20     
21     //@return: return next node
22     public TreeNode next() {
23         // write your code here
24         if(!hasNext()) return null;
25         TreeNode cur = stack.pop();
26         if(cur.right == null) next = null;
27         else next = cur.right;
28         return cur;
29     }
30 }

View Code

 

2 二叉查找树中搜索

注意点:见代码

    不一定要完全遍历二叉树,可以在遍历前判断下来减少遍历的量。

    if(root.val > k1)  helper(root.left, result, k1, k2);

http://www.lintcode.com/zh-cn/problem/search-range-in-binary-search-tree/

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 //可以定义一个 ArrayList<Integer> result的成员变量,这样helper中就不需要resul作为参数一直传递添加了。
 2   public ArrayList<Integer> searchRange(TreeNode root, int k1, int k2) {
 3      ArrayList<Integer> result = new ArrayList<Integer> ();
 4      helper(root, result, k1, k2);
 5      return result;
 6  }
 7  private void helper(TreeNode root, ArrayList<Integer>  result, int k1, int k2) {
 8      if(root == null) return;
 9      helper(root.left, result, k1, k2);
10      if(root.val >= k1 && root.val <= k2) result.add(root.val);
11      helper(root.right, result, k1, k2);
12      return;
13  }

View Code

 

3 二叉树中插入结点

http://www.lintcode.com/en/problem/insert-node-in-a-binary-search-tree/

注意点:非递归的插入方式

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  public TreeNode insertNode(TreeNode root, TreeNode node) {
 2         // write your code here
 3         if(root == null) {
 4             root = node;
 5             return root;
 6         }
 7         if(root.val <= node.val) {
 8             root.right = insertNode(root.right, node);
 9             
10         } else {
11             root.left = insertNode(root.left, node);
12         }
13         return root;
14     }
15 //非递归
16  public TreeNode insertNode(TreeNode root, TreeNode node) {
17         // write your code here
18         if(root == null) {
19             root = node;
20             return root;
21         }
22         TreeNode last = null, temp = root;
23         while(temp != null) {
24             last = temp;
25             if(temp.val <= node.val) temp = temp.right;
26             else temp = temp.left;
27         }
28         if(last != null) { //可以不判断,last不可能为null
29             if(last.val <= node.val) last.right = node;
30             else last.left = node;
31         }
32         return root;
33     }
34     

View Code

4  二叉树删除结点

http://www.lintcode.com/en/problem/remove-node-in-binary-search-tree/

注意点:见代码

    结点的传递是地址传递,所以将待改变结点的引用传入函数,函数操作后,整个树是会发生变化的。

    待删结点有两个子树的删除方式:

  九章算法_九章算法(杭州)科技有限公司

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public TreeNode removeNode(TreeNode root, int value) {
 2         TreeNode dummy = new TreeNode(0); //dummy的值随便取,反正不输出,为了仅仅是给root设个头
 3         dummy.left = root; 
 4         
 5         TreeNode parent = findNode(dummy, root, value);
 6         TreeNode node; //待删结点
 7         if (parent.left != null && parent.left.val == value) {
 8             node = parent.left;
 9         } else if (parent.right != null && parent.right.val == value) {
10             node = parent.right;
11         } else {
12             return dummy.left ;  //待删结点不存在
13         }
14         
15         deleteNode(parent, node);
16         
17         return dummy.left ;
18     }
19     
20     private TreeNode findNode(TreeNode parent, TreeNode node, int value) {  //返回待删结点的父节点,待删的不存在也返回父节点
21         if (node == null) {
22             return parent;
23         }
24         
25         if (node.val == value) {
26             return parent;
27         }
28         if (value < node.val) {
29             return findNode(node, node.left, value);
30         } else {
31             return findNode(node, node.right, value);
32         }
33     }
34     
35     private void deleteNode(TreeNode parent, TreeNode node) {
36         if (node.right == null) {
37             if (parent.left == node) {
38                 parent.left = node.left;
39             } else {
40                 parent.right = node.left;
41             }
42         } else {
43             TreeNode temp = node.right;
44             TreeNode father = node;
45             
46             while (temp.left != null) {
47                 father = temp;
48                 temp = temp.left;
49             }
50             
51             if (father.left == temp) {
52                 father.left = temp.right;
53             } else {
54                 father.right = temp.right;
55             }
56             
57             if (parent.left == node) {
58                 parent.left = temp;
59             } else {
60                 parent.right = temp;
61             }
62             
63             temp.left = node.left;
64             temp.right = node.right;
65         }
66     }

View Code

 DP——————————————————————————————————————————————————————–

满足下面三个条件之一:
● 求最大值最小值
● 判断是否可行
● 统计方案个数
则 极有可能 是使用动态规划求解

序列型dp 递推表达式f[] 里代表着含有0个~length个字符,所以数组的长度定义为length+1;
区间型dp 递推表达式f[] 里代表着坐标,所以数组的长度定义为length;

 

1  数字三角形

http://www.lintcode.com/zh-cn/problem/triangle/

疑问: 用HashMap怎么存?编译不通过?????

注意点:top- down 、down – top、 记忆化搜索

    初始化三角形的顶点和两个侧边

错误点:

 

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 //搜索记忆,查找过的结点不需要再查一次,所以复杂度为O(n * n)
 2 int[][] triangle = null;
 3 int[][] sumMin = null;
 4 int n;
 5 public int minimumTotal(int[][] triangle) {
 6     if(triangle == null || triangle.length == 0 || triangle[0].length == 0) return 0;
 7     this.n = triangle.length;
 8     this.triangle = triangle;
 9     this.sumMin = new int[n][n];
10     for(int i = 0; i< n; i++) {
11         for(int j = 0; j < n ; j++) sumMin[i][j] = Math.MAX_VALUE;
12     }
13     
14     return helper(0, 0);
15 }
16 private  int helper(int x, int y) {
17     if(x >= n) return 0;
18     if(sumMin[x][y] != Math.MAX_VALUE) return sumMin[x][y];
19     sumMin[x][y] = Math.min(helper(x+1, y),helper(x+1,y+1)) + triangle[x][y];
20     return  sumMin[x][y];
21 }
22 // 同上,用哈希表存查过的结点
23 int[][] triangle = null;
24 HashMap<int[], Integer> sumMin = new HashMap<int[], Integer>();
25 int n;
26 public int minimumTotal(int[][] triangle) {
27     if(triangle == null || triangle.length == 0 || triangle[0].length == 0) return 0;
28     this.n = triangle.length;
29     this.triangle = triangle;
30     for(int i = 0; i< n; i++) {
31         for(int j = 0; j < n ; j++) sumMin[i][j] = Math.MAX_VALUE;
32     }
33     
34     return helper(0, 0);
35 }
36 private  int helper(int x, int y) {
37     if(x >= n) return 0;
38     if(sumMin.containsKey({x,y})) return sumMin.get({x,y});
39     int value = Math.min(helper(x+1, y),helper(x+1,y+1)) + triangle[x][y];
40     sumMin.put({x,y}, value);
41     return  value;
42 }
43 //top - down
44 public int minimumTotal(int[][] triangle) {
45     if(triangle == null || triangle.length == 0 || triangle[0].length == 0) return 0;
46     int row = triangle.length;
47     for(int i =1; i < row; i++) {
48         triangle[i][0] +=  triangle[i-1][0];
49         triangle[i][i] += triangle[i-1][i-1];
50     }
51     for(int i = 2; i < row; i++) {
52         for(int j =1; j < i; j++) {
53             triangle[i][j] += Math.min(triangle[i-1][j],triangle[i-1][j-1]);
54         }
55     }
56     for(int i = 1; i < row; i++) {
57         triangle[row-1][0] = Math.min(triangle[row-1][i],triangle[row-1][0]);
58     }
59     return triangle[row-1][0];
60 }
61 //down - top
62 public int minimumTotal(int[][] triangle) {
63     if(triangle == null || triangle.length == 0 || triangle[0].length == 0) return 0;
64     int row = triangle.length;
65     for(int i= row -2; i >=0; i--) {
66         for(int j=0; j<= i; j++)
67         triangle[i][j] += Math.min(triangle[i+1][j], triangle[i+1][j+1]);
68     }
69     return triangle[0][0];
70 }

View Code

 

2 爬梯子

http://www.lintcode.com/zh-cn/problem/climbing-stairs/

注意点:类似斐波那契别超时~

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public int climbStairs(int n) { 
 2      if(n == 0) return 1;
 3     a = 1;
 4     b = 1;
 5     for(int i = 2; i <= n; i++) {
 6         int c = a+ b;
 7         c= b;
 8         a = b;
 9     }
10     return c;
11  }
12 //---------------------
13  public int climbStairs(int n) { 
14     int[] f = new int[n+1];
15     if(n == 0) return 1;
16     f[0] = 1;
17     f[1] = 1;
18     for(int i = 2; i <= n; i++) {
19         f[i] = f[i - 1] + f[i - 2];
20     }
21     return f[n];
22  }

更新版本1

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 // 递归调用会超时,因为有重复计算的过程
 2    public int climbStairs(int n) {
 3        if(n == 0) return 1;
 4        if(n == 1) return 1;
 5        return climbStairs(n-2)+climbStairs(n-1);
 6    }
 7  //  加入记忆化搜索,还超时
 8  int[] result = null;
 9    public int climbStairs(int n) {
10        result = new int[n];
11        Arrays.fill(result, -1);
12        if(n == 0) return 1;
13        if(n == 1) return 1;
14        result[0] = 1,   result[1] = 1;
15        return helper(n);
16    }
17    private int helper(n) {
18        if(result[n] != -1) return result[n];
19        return helper(n-1) + helper(n-2);
20    }
21    //
22     public int climbStairs(int n) {
23          if(n <=1) return 1;
24          int last = 1, last_last = 1;
25          int now = 0;
26          for(int i=1 ; i< n;i++) {
27              now = last + last_last;
28              last_last = last;
29              last = now;
30          }
31          return now;
32      }

View Code

3 跳跃游戏

http://www.lintcode.com/zh-cn/problem/jump-game/

注意点:O(N * N)的时间复杂度

错误点:

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  //  me
 2    public boolean canJump(int[] A) {
 3         // wirte your code here
 4         if(A == null || A.length == 0) return false;
 5         int n = A.length;
 6         int pos =0;
 7         while(pos <= n -1) {
 8             if(A[pos] >= n - 1 - pos) return true;
 9             else {
10                 int temp = pos + A[pos];
11                 while(A[temp] == 0) {
12                     temp--;
13                     if(temp <= pos) return false;
14                 }
15                 pos = temp;
16             } 
17         }
18         return false;        
19     }
20 // greedy
21 public boolean canJump(int[] A) {
22     if(A == null || A.length == 0) return false;    
23     int farthest = A[0];
24     for(int i = 1; i< A.length; i++) {
25         if(farthest >= i && farthest < i+ A[i]) {
26             farthest = i + A[i];
27         }
28     }
29     return farthest>= A.length - 1;
30 }
31 //dp
32     public boolean canJump(int[] A) {
33     if(A == null || A.length == 0) return false;
34     boolean[] can = new boolean[A.length];
35     can[0] = true;
36     for(int i = 1; i < A.length; i++) {
37         for(int j = 0; j < i; j++) {
38             if(can[j] && A[j] + j >= i) {
39                 can[i] = true;
40                 break;
41             }
42         }
43     }
44     return can[A.length - 1];
45 }

View Code

4  跳跃游戏二

http://www.lintcode.com/zh-cn/problem/jump-game-ii/

注意点:

错误点:结果数组没有初始化,数组间的关系没搞清楚

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public int jump(int[] A) {
 2         // state
 3         int[] steps = new int[A.length];
 4 
 5         // initialize
 6         steps[0] = 0;
 7         for (int i = 1; i < A.length; i++) {
 8             steps[i] = Integer.MAX_VALUE;
 9         }
10 
11         // function
12         for (int i = 1; i < A.length; i++) {
13             for (int j = 0; j < i; j++) {
14                 if (steps[j] != Integer.MAX_VALUE && j + A[j] >= i) {
15                     //steps[i] = Math.min(steps[i], steps[j] + 1);
16                     steps[i] = steps[j] + 1;
17                     break; //贪心
18                 }
19             }
20         }
21         
22         // answer
23         return steps[A.length - 1];
24     }

View Code

5  two Sum

http://www.lintcode.com/en/problem/two-sum/

注意点: map里存需要的值和它的角标;

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 //dp
 2   public int[] twoSum(int[] numbers, int target) {
 3     // write your code here
 4     HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
 5     for(int i = 0 ; i< numbers.length; i++) {
 6         if(map.get(numbers[i]) != null) {
 7             int[] result = {map.get(numbers[i]) + 1, i+1};
 8             return result;
 9         }
10         // if在前,put在后,一定要这样,先看有没有再放。
11         map.put(target - numbers[i], i);
12     }
13     int[] result = {};
14     return result;
15  }
16 //---------------------------
17 public int[] twoSum(int[] numbers, int target) {
18     // write your code here
19     if(numbers == null || numbers.length <= 1) return null;
20     for(int i = 0; i< numbers.length - 1; i++) {
21         for(int j = i+1; j< numbers.length; j++) {
22             if(numbers[i] == target - numbers[j]) return new int[]{i + 1, j + 1};
23         }
24     }
25     return null;
26  }

View Code

 6 k sum   不会

http://www.lintcode.com/zh-cn/problem/k-sum/

 7 最长上升连续子序列

http://www.lintcode.com/zh-cn/problem/longest-increasing-continuous-subsequence/

注意点:

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public int longestIncreasingContinuousSubsequence(int[] A) {
 2     if(A == null || A.length == 0) return 0;
 3     int[] result = new int[A.length];
 4     Arrays.fill(result, 1);
 5     int max = 1;
 6     for(int i = 1; i< A.length; i++) {
 7         if(result[i -1] == 1) {
 8             result[i] =2;
 9             if(max < result[i]) max = result[i];
10             continue;
11         }
12         if(A[i-2] < A[i -1] && A[i-1] < A[i] ||
13         A[i-2] > A[i-1] && A[i-1] > A[i])
14         result[i] =  result[i- 1]+1;
15         else result[i] = 2;
16         if(max < result[i]) max = result[i];
17     }
18     return max;
19 }
20 //------------------------------------------------------------
21 public int longestIncreasingContinuousSubsequence(int[] A) {
22     if(A == null || A.length == 0) return 0;
23     int max = 1;
24     int length =1;
25     for(int i = 1; i < A.length; i++) {
26         if(A[i] > A[i-1]) length++;
27         else length=1;
28         max= Math.max(length, max);
29     }
30     for(int i = A.length -2; i >=0; i--) {
31         if(A[i+1] < A[i]) length++;
32         else length=1;
33         max= Math.max(length, max);
34     }
35     return max;
36 }

View Code

 8 最长连续序列

http://www.lintcode.com/zh-cn/problem/longest-consecutive-sequence/

注意点: 求数组中连续序列个数的两种方式: 

       先排序,在求最长的递增序列长度;

       把元素放到set里,之后遍历数组,查找是否包含连续序列,见代码。

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public int longestConsecutive(int[] num) {
 2      if(num == null || num.length == 0) return 0;
 3      int[] sortArray = bucketSort(num);
 4      int[] f= new int[sortArray.length];
 5      f[0] = 1;
 6      int maxLen = 1;
 7      for(int i = 1; i < sortArray.length; i++) {
 8          f[i] = 1;
 9          if(sortArray[i] == sortArray[i -1] + 1) {
10              f[i] = f[i - 1] + 1;
11          } else if(sortArray[i] == sortArray[i -1]) f[i] = f[i - 1];
12          if(maxLen < f[i]) maxLen = f[i];
13      }
14      return maxLen;
15  }
16  private int[] bucketSort(int[] num) {
17      if(num == null || num.length == 0) return null;
18      int max = 0, min = 0;
19      for(int i : num) {
20          if(max <= i) max = i;
21          if(min >= i) min = i;
22      }
23      long[] bucket = new long[max - min + 1];
24      for(int i : num) {
25          //如果min= 3, 4应该放在1的位置
26          bucket[i - min]++;
27      }
28      int[] result = new int[num.length];
29      int i = 0;
30      for(int j = 0; j < bucket.length; j++) {
31         if(bucket[j] == 0) continue;
32         while(bucket[j] != 0) {
33             result[i] = j + min;
34             bucket[j] -= 1;
35             i++;
36         }        
37      }
38      return result;
39  }

先进行桶排序,有NegativeArraySizeException

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  public int longestConsecutive(int[] num) {
 2      if(num == null || num.length == 0) return 0;
 3      Set<Integer> set = new HashSet<Integer>();
 4      for(int i : num) set.add(i);
 5      int max = 0;
 6      for(int i = 0; i< num.length; i++) {
 7          int down = num[i];
 8          while(set.contains(down)) {
 9              set.remove(down);
10              down--;
11          }
12          int up = num[i] + 1;
13          while(set.contains(up)) {
14              set.remove(up);
15              up++;
16          }
17          max = Math.max(max, up-down - 1);
18      }
19      return max;
20  }

View Code

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public int longestConsecutive(int[] num) {
 2     if(num == null || num.length == 0) return 0;
 3     int max = 1;
 4     Arrays.sort(num);
 5     HashMap<Integer,Integer> map = new HashMap<Integer, Integer>();
 6     for(int i = 0; i < num.length; i++) {
 7         if(map.get(num[i]) != null) {
 8             map.put(num[i] + 1, map.get(num[i]) + 1);
 9         } else     map.put(num[i] + 1, 1);
10         max = Math.max(max, map.get(num[i] + 1));
11     }
12     return max;
13 }
14 //用set存放,while循环找顺序序列,而不需要提前排序
15  public int longestConsecutive(int[] num) {
16     if(num == null || num.length == 0) return 0;
17     HashSet<Integer> set = new HashSet<Integer>();
18     for(int i = 0; i < num.length; i++) {
19         set.add(num[i]);
20     }
21     int max = 1;
22     for(int i=0;i< num.length; i++) {
23         int down = num[i] - 1;
24         while(set.contains(down)) {
25             set.remove(down);
26             down--;
27         }
28         int up = num[i] + 1;
29         while(set.contains(up)) {
30             set.remove(up);
31             up++;
32         }
33         max = Math.max(max, up - down -1);
34     }
35     return max;
36 }

View Code

 9 最大子数组  部分答案看不懂,还是不懂~~~

http://www.lintcode.com/zh-cn/problem/maximum-subarray/

注意点:

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public int maxSubArray(int[] nums) {
 2     //错误点: 没有考虑到 4,-1,2,1 这种情况,应该是6,目前结果时4.
 3     if(nums == null || nums.length == 0) return 0;
 4     int[] f = new int[nums.length];
 5     int max = f[0] =  nums[0];
 6     for(int i = 1; i < nums.length; i++) {
 7         if(nums[i] >= 0) {
 8             if(f[i - 1] >=0) f[i] = f[i-1] + nums[i];
 9             else f[i] = nums[i];
10         } else {
11             if(f[i - 1] < nums[i]) f[i] = nums[i];
12             else f[i] = nums[i];
13             
14         }
15         max = Math.max(max, f[i]);
16     }
17     return max;
18 }
19 public int maxSubArray(int[] nums) {
20     if(nums == null || nums.length == 0) return 0;
21     int max = nums[0], sum = 0;
22     for(int i = 0; i < nums.length; i++) {
23         sum +=nums[i];
24         max = Math.max(sum, max);
25         sum = Math.max(sum, 0);
26     }
27     return max;
28 }

1

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  public int maxSubArray(int[] nums) {
 2     int max = Integer.MIN_VALUE, sum = 0;
 3     if(nums == null || nums.length  ==0) return 0;
 4     for(int i =0; i < nums.length; i++) {
 5         sum += nums[i];
 6         max = Math.max(sum, max); //用max记录每次sum后现阶段遇到的最大sum和。
 7         sum = Math.max(0, sum);  //每次sum的和一定要大于0,否则之前sum的数字就不要了。
 8     }
 9     return max;
10  }
11  //---------------------------------------------------------------
12   public int maxSubArray(int[] nums) {
13     int max = Integer.MIN_VALUE, sum = 0;
14     if(nums == null || nums.length  ==0) return 0;
15     int[] partMax = new int[nums.length];
16     int[] globalMax = new int[nums.length];
17     partMax[0] = globalMax[0] = nums[0];
18     
19     for(int i = 1; i < nums.length; i++) {
20         partMax[i] = Math.max(partMax[i - 1] + nums[i], nums[i]);
21         globalMax = Math.max(partMax[i], globalMax[i-1]);
22     }
23     return globalMax[nums.length - 1];
24 }

View Code

 10 分割回文串2

http://www.lintcode.com/zh-cn/problem/palindrome-partitioning-ii/#

注意点:

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 private boolean[][] getInstance(String s) {
 2     boolean[][] str = new boolean[s.length()][s.length()];
 3     for(int i = 0; i < s.length(); i++) {
 4         str[i][i] = true;
 5     }
 6     for(int i = 0; i < s.length() - 1; i++) {
 7         str[i][i+1] = s.charAt(i) == s.charAt(i+1);
 8     }
 9     for(int len = 2;len <s.length(); len++) {
10         for(int i = 0; i + len < s.length(); i++) {
11             str[i][i+len] = str[i + 1][i+len -1] && s.charAt(i) == s.charAt(i+len);
12         }
13     }
14     return str;
15 }
16 public int minCut(String s) {
17     if(s==null || s.length() ==0) return 0;
18     boolean[][] str = getInstance(s);
19     int[] f = new int[s.length() + 1];
20     for(int i = 0; i < f.length; i++) {
21         f[i] = i - 1;
22     }
23     for(int i= 1; i <= s.length(); i++) {
24         for(int j = 0; j < i; j++) {
25             if(str[j][i-1]) {
26                 f[i]= Math.min(f[i], f[j] + 1);
27             }
28         }
29     }
30     return f[f.length -1];
31 }

5-24 简化写法

 

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 for(int i = 0; i<f.length; i++) {  
 2         f[i] = i - 1;  //i长度的字符串,最多分割i-1刀可以构成回文串,设为Integer.MAX_VALUE也行,关键是f[0]=-1,f[1]=0
 3     }
 4     for(int i = 1; i <= s.length(); i++) { //长度为i的字符串
 5         for(int j = 0; j< i; j++) {              //两个子串: 0~j-1, j~i-1,判断是否是回文串。
 6             if(str[j][i-1]) {
 7                 f[i] = Math.min(f[i], f[j] + 1);  //f[j]已经在之前求出来了,表示0~j-1这j个字符至少分几刀可以形成回文串
 8             }
 9         }
10     }

部分解释

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1   private boolean isPalindrome(String s, int start, int end) {
 2     for(int i = start, j = end; i < j; i++,j--) {
 3         if(s.charAt(i) != s.charAt(j)) return false;        
 4     }
 5     return true;
 6 }
 7 private boolean[][] getPalindromeInstance(String s) {
 8     boolean[][] str = new boolean[s.length()][s.length()];
 9     for(int i = 0; i<s.length(); i++) {
10         str[i][i] = true;
11     }
12     for(int i = 0; i<s.length() - 1; i++) {
13         str[i][i+1] = isPalindrome(s, i, i+1);
14     }
15     for(int len = 2; len < s.length(); len++) {  //长度是len+1的子串
16         for(int i = 0; i + len < s.length(); i++) {    //len+i代表尾角标位置
17             str[i][i+len] = isPalindrome(s, i + 1, i+len - 1) && s.charAt(i) == s.charAt(i+len);
18         }
19     }
20     return str;
21 }
22 public int minCut(String s) {
23      if(s==null || s.length() == 0) return 0;
24      boolean[][] str = getPalindromeInstance(s);
25      
26      int[] f = new int[s.length() + 1];
27      for(int i = 0; i < f.length; i++) {  //长度为i的字符串最多分割i-1次就可以都是回文串,也可以将f[i]设为Integer.MAX_VALUE;
28          f[i] = i - 1;
29      }
30      for(int i = 1; i<= s.length(); i++) {//i个字符构成回文串
31         for(int j = 0; j < i; j++) {
32             if(str[j][i -1]) {
33                 f[i] = Math.min(f[i],f[j] + 1);
34             }
35         }
36      }
37      return f[f.length - 1];
38 }

View Code

 11  单词分割

http://www.lintcode.com/problem/word-break

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public boolean wordBreak(String s, Set<String> dict) {
 2     if(s == null || s.length() == 0) return true;
 3     if(dict == null ||dict.size() == 0) return false;
 4     int wordLen = 0;
 5     for(String s1 : dict) {
 6         wordLen = Math.max(wordLen, s1.length());
 7     }
 8     boolean f[] = new boolean[s.length() + 1];
 9     f[0] = true;
10     for(int i = 1; i <= s.length(); i++) {   //i表示包含i个单词,j表示最后一个单词的长度
11         f[i] = false;
12         //0~i-1   0~i-j-1,i-j~i-1
13         for(int j=1;j<=wordLen && j<=i; j++) {
14             if(f[i-j]) {
15                 if(dick.contains(s.subString(i-j, i-1))) {
16                     f[i] = true;
17                     break;
18                 }
19             }
20         }
21     }
22     return f[f.length - 1];
23 }

update 1

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public boolean wordBreak(String s, Set<String> dict) {
 2     if(s == null || dict == null) return false;
 3     if(dict.size() == 0) {
 4         if(s.length() == 0 ) return true;
 5         return false;
 6     }
 7     int maxLen = 0;
 8     for(String s1 : dict) {
 9         maxLen = Math.max(s1.length(), maxLen);
10     }
11     boolean[] canBreak = new boolean[s.length() + 1];
12     canBreak[0] = true;
13     for(int i = 1; i <= s.length(); i++) {
14         canBreak[i] = false;
15         for(int lastWordLen = 1; lastWordLen <=i && lastWordLen <= maxLen; lastWordLen++) {
16             if(canBreak[i - lastWordLen]) {    //最后一个单词的下标是 [i - lastWordLen, i) 左开右闭,包含的字符个数为lastWordLen
17                 String word = s.substring(i - lastWordLen, i); 
18                 if(dict.contains(word)) {
19                     canBreak[i] = true;
20                     break;
21                 }
22             }
23         }
24     }
25     return canBreak[s.length()];
26 }

View Code

 12 最长公共子序列  LCS

http://www.lintcode.com/zh-cn/problem/longest-common-subsequence/#

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public int longestCommonSubsequence(String A, String B) {
 2     if(A == null || B == null || A.length() == 0 || B.length() == 0) {
 3         return 0;
 4     }
 5     int m = A.length(), n = B.length();
 6     int[][] f = new int[m+1][n+1];
 7     for(int i = 1; i <=m; i++) {
 8         f[i][0] = 0;
 9     }
10     for(int i = 0; i <=n; i++) {
11         f[0][i] = 0;
12     }
13     for(int i = 1; i<=m; i++) {
14         for(int j =1; j<=n; j++) {
15             if(A.charAt(i-1) == B.charAt(j-1)) {
16                 f[i][j] = f[i-1][j-1]+1;
17             } else {
18                 f[i][j] = Math.max(f[i][j-1],f[i-1][j]);
19             }
20         }
21     }
22     return f[m][n];
23 }

update 1

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1     public int longestCommonSubsequence(String A, String B) {
 2     if(A == null || B == null || A.length() == 0 || B.length() == 0) return 0;
 3     int[][] lcs = new int[A.length() + 1][B.length() + 1];
 4     for(int i = 0; i <= A.length(); i++) {
 5         lcs[i][0] = 0;
 6     }
 7     for(int j = 0; j <= B.length(); j++) {
 8         lcs[0][j] = 0;
 9     }
10     for(int i = 1; i <= A.length(); i++) {
11         for(int j = 1; j <= B.length(); j++) {
12             if(A.charAt(i-1) == B.charAt(j-1)) {
13                 lcs[i][j] =  Math.max(lcs[i - 1][j - 1]+1, Math.max(lcs[i - 1][j], lcs[i][j - 1]));  //只写lcs[]][]+1即可,不用判断的
14             } else {
15                 lcs[i][j] =  Math.max(lcs[i - 1][j - 1]+0, Math.max(lcs[i - 1][j], lcs[i][j - 1]));
16             }
17         }
18     }
19     return lcs[A.length()][B.length()];
20 }

View Code

 13  最长公共子串

http://www.lintcode.com/zh-cn/problem/longest-common-substring/#

问题: contains复杂度O(n)???

注意点:

错误点: f[i][j]的含义搞不太懂,想一想递归关系之间的具体实现过程。在循环过程中,公共子串中的每一个字符都会作为最后一个字符去进行比较。

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public int longestCommonSubstring(String A, String B) {
 2     if(A == null || B == null || A.length() == 0 || B.length() == 0) return 0;
 3     int max = 0;
 4     for(int i = 0; i < A.length(); i++) {
 5         for(int j= i + 1; j <= A.length(); j++) {
 6             if(B.contains(A.substring(i,j))) max = Math.max(max, j- i);
 7         }
 8     }
 9     return max;                //O(n * n * n)
10  }
11 //----------------------------------------------------
12 public int longestCommonSubstring(String A, String B) {
13     if(A == null || B == null || A.length() == 0 || B.length() == 0) return 0;
14     
15     int[][] lcs = new int[A.length() + 1][B.length() + 1];
16     for(int i = 1; i <= A.length(); i++) {
17         for(int j = 1; j <= B.length(); j++) {
18             if(A.charAt(i-1) == B.charAt(j-1)) {
19                 lcs[i][j] = lcs[i - 1][j - 1]+1;
20             } else {
21                 lcs[i][j] =  0;
22             }
23         }
24     }
25     
26     int max = 0;    
27     for(int i = 1; i <= A.length(); i++) {
28         for(int j = 1; j <= B.length(); j++) {
29             max = Math.max(max, lcs[i][j]);
30         }
31     }
32     return max;
33 }

View Code

 14 编辑距离

http://www.lintcode.com/zh-cn/problem/edit-distance/#

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  // 为什么要死记公式啊,先求lcs再去匹配一致,考虑并不周全     abc     cab  
 2  public int minDistance(String word1, String word2) {
 3     if(word1 == null || word2 == null) {
 4         if(word1 != null) return word1.length();
 5         if(word2 != null) return word2.length();
 6         return 0;
 7     }
 8     int[][] lcs = new int[word1.length() + 1][word2.length() + 1];
 9     for(int i = 1; i <= word1.length(); i++) {
10         for(int j = 1; j <= word2.length(); j++) {
11             if(word1.charAt(i-1) == word2.charAt(j-1)) {
12                 lcs[i][j] = lcs[i - 1][j - 1]+1;
13             } else {
14                 lcs[i][j] =  0;
15             }
16         }
17     }
18     int max = 0;    
19     for(int i = 1; i <= word1.length(); i++) {
20         for(int j = 1; j <= word2.length(); j++) {
21             max = Math.max(max, lcs[i][j]);
22         }
23     }
24     return Math.max(word1.length()-max, word2.length() - max);
25 }
26 //----------------------
27  public int minDistance(String word1, String word2) {
28     if(word1 == null || word2 == null) {
29         if(word1 != null) return word1.length();
30         if(word2 != null) return word2.length();
31         return 0;
32     }
33     int[][] f =  new int[word1.length() + 1][word2.length() + 1];
34     for(int i = 0; i <= word1.length(); i++) f[i][0] = i;
35     for(int j = 0; j <= word2.length(); j++) f[0][j] = j;
36     
37     for(int i = 1; i <=word1.length(); i++) {
38         for(int j = 1; j <= word2.length(); j++) {
39             if(word1.charAt(i - 1) == word2.charAt(j - 1)) {
40                 f[i][j] = Math.min(Math.min(f[i-1][j] + 1, f[i][j-1]+1),f[i- 1][j - 1]);
41             } else {
42                 f[i][j] = Math.min(Math.min(f[i-1][j] + 1, f[i][j-1]+1),f[i- 1][j - 1] + 1);
43             }
44         }
45     }
46     return f[word1.length()][word2.length()];
47  }

View Code

 

链表—————————————————————————————-

注意事项: 调用node.next时,一定要确保node非null,否则空指针异常。

     链表的head 和head.next是否为空先判断下,类似二叉树root要单独拿出来考虑一样。

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 链表的基本操作
 2 1. Insert a Node in Sorted List
 3 2. Remove a Node from Linked List
 4 3. Reverse a Linked List
 5 4. Merge Two Linked Lists
 6 5. Middle of a Linked List
 7 
 8 1.  // 最简单的方法
 9     private ListNode reverse(ListNode head) {
10         if(head == null || head.next == null) return head;
11         ListNode prev = null;
12         while(head!= null ) {
13             ListNode temp = head.next;
14             head.next = prev;
15             prev = head;
16             head = temp;
17         }
18         return prev;
19     }
20     //另一种写法
21  private ListNode reverse(ListNode head) {
22      if(head == null || head.next == null) return head;
23      ListNode tail = head;
24      ListNode next =tail.next;
25      while(next != null) {
26          ListNode temp = next.next;
27          next.next =tail;
28         tail = next;
29         next =temp;
30      }        
31      head =tail;
32      tail.next = null;
33      return head;
34  }
35 4. private ListNode merge(ListNode left, ListNode right) {
36     ListNode dummy = new ListNode(0), tail = dummy;
37     while(left != null && right != null) {
38         tail.next = left;
39         left = left.next;
40         tail = tail.next;
41         tail.next = right;
42         right.next = right;
43         tail = tail.next;
44     }
45     if(left != null) tail.next = left;
46     else tail.next = right;
47     return dummy.next;
48 }
49 5.   快慢指针
50     private ListNode getMid(ListNode head) {}
51      //12345  要找到3
52      if(head == null || head.next == null) return head;
53      ListNode slow = head, fast = head;
54      while(fast.next != null && fast.next.next != null) {
55          slow = slow.next;
56          fast = fast.next.next;
57      }
58      return slow;
59     //查找倒数第n个结点
60     private ListNode find(ListNode head) {
61           ListNode slow = head, fast = head;
62     // 1 2 3 4 5  找4,倒数第2个,需要在fast走第二步的时候,slow开始走第一步
63     int i = 0;
64     while(fast.next != null) {
65         i++;
66         fast = fast.next;
67         if(i < 2) coutinue;
68         slow = slow.next;
69     }
70     return slow;
71     }

链表基本操作

 

1  删除排序链表2

http://www.lintcode.com/zh-cn/problem/remove-duplicates-from-sorted-list-ii/

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 //----------------运行超时
 2   public static ListNode deleteDuplicates(ListNode head) {
 3         // write your code here
 4         if(head == null || head.next == null) return head;
 5         ListNode prev = null;
 6         ListNode curr = head;
 7         Map<ListNode,Integer> map = new HashMap<ListNode,Integer>();
 8         int value = 0;
 9         while(curr != null) {
10             if(map.get(curr) != null) {
11                 map.put(curr,map.get(curr) + 1);
12             } else {
13                 map.put(curr,1);
14             }
15         }
16         prev.next = head;
17         curr = head;
18         ListNode currNext = curr.next;
19         while(currNext != null) {
20             if(map.get(currNext) != 1) {
21                 curr = currNext;
22                 currNext.next = currNext.next;
23             }
24         }
25         return prev.next;
26     }
27 //--------------------------------------------------
28  public static ListNode deleteDuplicates(ListNode head) {
29      if(head == null || head.next == null) return head;
30      ListNode dummy = new ListNode(0);
31      dummy.next = head;
32      //只要不用next操作,引用再怎么换也不会影响链表。
33      head = dummy;
34      while(head.next != null && head.next.next != null) {
35          if(head.next.val == head.next.next.val) {
36              int val = head.next.val;
37              while(head.next != null && head.next.val == val) {
38                  head.next = head.next.next;
39              }
40          } else {
41              head = head.next;
42          }
43      }
44      return dummy.next;
45  }

View Code

2   删除排序链表

http://www.lintcode.com/zh-cn/problem/remove-duplicates-from-sorted-list/#

注意点:引入dummy的目的是为了不用将头结点删除与否分情况讨论。这里头结点肯定不用删除,所以可以不引入dummy。

            也可以沿用删除链表2的解法,稍微改改。

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  public static ListNode deleteDuplicates(ListNode head) { 
 2         // write your code here
 3         if(head == null || head.next == null) return head;
 4         ListNode dummy = new ListNode(0);
 5         dummy.next = head;
 6         head = dummy;
 7         while(head.next != null && head.next.next != null) {
 8             if(head.next.val == head.next.next.val) {
 9                 head.next = head.next.next;
10             } else head = head.next;
11         }
12         return dummy.next;
13     }  

View Code

3  反转链表

http://www.lintcode.com/zh-cn/problem/reverse-linked-list/

注意点: 死记解法,四步骤

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  public ListNode reverse(ListNode head) {
 2         // write your code here
 3        ListNode prev = null;
 4        while(head != null) {
 5            ListNode temp = head.next;
 6            head.next = prev;
 7            prev = head;
 8            head = temp;
 9        }
10        return prev;
11     }

View Code

4   反转链表2

http://www.lintcode.com/zh-cn/problem/reverse-linked-list-ii/

错误点: 第二个for循环里写成了if(nPost.next== null) return null;

注意点: 第二个for循环里,n~m ,共n-m+1个数字,需要nNode走n-m次,i=m+1时,n移动了一次,所以i最后出了循环需要等于m+n-m = n

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public ListNode reverseBetween(ListNode head, int m , int n) {
 2       if(head == null || m >= n) return head;
 3       ListNode dummy = new ListNode(0);
 4       dummy.next = head;
 5       head = dummy;
 6       for (int i = 1; i < m; i++) {
 7           if(head != null) head = head.next;
 8           else return null;
 9       }
10       ListNode mprev = head;
11       ListNode mNode = mprev.next;
12       ListNode nNode = mNode;
13       ListNode nPost = nNode.next;
14       for(int i = m; i < n;i++) {
15           if(nPost == null) return null;
16           ListNode temp = nPost.next;
17           nPost.next = nNode;
18           nNode = nPost;
19           nPost = temp;
20       }
21       mprev.next = nNode;
22       mNode.next = nPost;
23       return dummy.next;
24       
25   }

View Code

5  链表划分

http://www.lintcode.com/zh-cn/problem/partition-list/

注意点: 将链表分成两个子链,左链放比指定数小的,右链连比指定数大的,最后再将他们合并。

     leftDummy和rightDummy保持不动,作为头指针,然后从它们的位置发出left和right指针,作为尾指针,依次移动记录当前子链表的最后一个位置。

      头指针.next=头结点,尾指针=尾结点

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public ListNode partition(ListNode head, int x) {
 2        if(head == null) return head;
 3        ListNode leftDummy =  new ListNode(0);
 4        ListNode rightDummy =  new ListNode(0);
 5        ListNode left = leftDummy, right = rightDummy;
 6        while(head != null) {
 7            if(head.val < x) {
 8                left.next = head;
 9                left = head;
10            } else {
11                right.next = head;
12                right = head;
13            }
14            head = head.next;
15        }
16        right.next = null;
17        left.next = rightDummy.next;
18        return leftDummy.next;
19    }

View Code

 6  链表排序

http://www.lintcode.com/zh-cn/problem/sort-list/#

注意点: 

错误点: sortList(ListNode head) 里if(head == null )而不判断head.next会报错,为啥??????

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1   private ListNode findMid(ListNode head) {
 2         ListNode slow = head, fast = head.next;
 3         while(fast.next != null && fast.next.next != null) {
 4             fast = fast.next.next;
 5             slow = slow.next;
 6         }
 7         return slow;
 8         //  12345   return 2;
 9    }
10    private ListNode merge(ListNode head1, ListNode head2) {
11        //dummy是合并后主链表的头,tail是尾。head1或head2中每当有一个结点链入主链,那链入的那个结点就可以
12        //在原先的链表中删除了,同时把原先的链表的头往后移。因为主链中加入了一个结点,所以主链的tail后移一次。
13        ListNode dummy = new ListNode(0), tail = dummy;
14        while(head1 != null && head2 != null) {
15            if(head1.val < head2.val) {
16                tail.next = head1;
17                head1 = head1.next;
18            } else {
19                tail.next = head2;
20                head2 = head2.next;
21            }
22            tail = tail.next;
23        }
24        //head1或head2有一个都链入主链后,把另一个非空的原先链表在链到主链尾部
25        //(这时原先链表中的后面位置的结点并没有进行排序。)
26        //最后返回的结果只是将head1或者head2进行排序了。(head1为空,则代表它完成排序了)
27        //要保证最后都有序,则head1和head2必须先有序。
28        if(head1 != null) {
29            tail.next = head1;
30        } else {
31            tail.next = head2;
32        }
33        return dummy.next;
34    }
35    
36    public ListNode sortList(ListNode head) {
37        if(head == null || head.next == null) return head;
38        ListNode mid = findMid(head);
39        ListNode right = sortList(mid.next);
40        mid.next = null; 
41        ListNode left = sortList(head);
42        return merge(left, right);
43     }

merge排序

7      重排链表

http://www.lintcode.com/zh-cn/problem/reorder-list/#

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public void reorderList(ListNode head) {  
 2        if(head == null || head.next == null) return;
 3        ListNode mid = getMid(head);
 4        ListNode right = reverse(mid.next);
 5        mid.next = null;
 6        head = merge(head, right);        
 7     }
 8     
 9 private ListNode getMid(ListNode head) {}
10     //12345   15243 要找到3
11     if(head == null || head.next == null) return head;
12     ListNode slow = head, fast = head;
13     while(fast.next != null && fast.next.next != null) {
14         slow = slow.next;
15         fast = fast.next.next;
16     }
17     return slow;
18 }
19 private ListNode reverse(ListNode head) {
20     if(head == null || head.next == null) return head;
21     
22     ListNode prev = null;
23     while(head!= null ) {
24         ListNode temp = head.next;
25         head.next = prev;
26         prev = head;
27         head = temp;
28     }
29     return prev;
30 }
31 private ListNode merge(ListNode left, ListNode right) {
32     ListNode dummy = new ListNode(0), tail = dummy;
33     while(left != null && right != null) {
34         tail.next = left;
35         left = left.next;
36         tail = tail.next;
37         tail.next = right;
38         right = right.next;
39         tail = tail.next;
40     }
41     if(left != null) tail.next = left;
42     else tail.next = right;
43     return dummy.next;
44 }

View Code

8    带环链表

http://www.lintcode.com/zh-cn/problem/linked-list-cycle-ii/#

注意点:快慢指针

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public ListNode detectCycle(ListNode head) {  
 2     if(head == null || head.next == null) return null;
 3     ListNode slow1 = head, fast = head;
 4     while(fast.next != null && fast.next.next != null) {
 5         slow1= slow1.next;
 6         fast = fast.next.next;
 7         if(slow1 == fast) {
 8             ListNode slow2 = head;
 9             while(true) {
10                 if(slow1 == slow2) return slow1;
11                 slow2 = slow2.next;
12                 slow1 = slow1.next;
13             }
14         }
15     }
16     return null;
17 }

View Code

 9  旋转链表

http://www.lintcode.com/zh-cn/problem/rotate-list/#

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  public ListNode rotateRight(ListNode head, int k) {
 2         if(head == null || head.next == null || k == 0) return head;
 3         int len = 0;
 4         ListNode temp = head;
 5         while( temp != null ) {
 6             len++;
 7             temp = temp.next;
 8         }
 9         k = k % len;
10         if(k == 0) return head;
11         ListNode tail= head;
12         int i = 1;
13         while( len - k != i) {
14             i++;
15             tail = tail.next;
16         }
17         ListNode newHead = tail.next, temp1 = newHead;
18         tail.next = null;
19         while(temp1.next != null) {
20             temp1 = temp1.next;
21         }
22         temp1.next = head;
23         return newHead;
24     }
25    //----------------------------------------------------
26     private int getLength(ListNode head) {
27         int length = 0;
28         while (head != null) {
29             length ++;
30             head = head.next;
31         }
32         return length;
33     }
34     
35     public ListNode rotateRight(ListNode head, int n) {
36         if (head == null) {
37             return null;
38         }
39         
40         int length = getLength(head);
41         n = n % length;
42         
43         ListNode dummy = new ListNode(0);
44         dummy.next = head;
45         head = dummy;
46         
47         ListNode tail = dummy;
48         //寻找倒数第n个结点(类似快慢指针实现的)
49         for (int i = 0; i < n; i++) {
50             head = head.next;
51         }  
52         while (head.next != null) {
53             tail = tail.next;
54             head = head.next;
55         }
56         
57         head.next = dummy.next;
58         dummy.next = tail.next;
59         tail.next = null;
60         return dummy.next;
61     }

View Code

 10   合并k个排序链表

http://www.lintcode.com/zh-cn/problem/merge-k-sorted-lists/

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 //两两合并----------------------------------------------
 2     public ListNode mergeKLists(List<ListNode> lists) {  
 3         if(lists == null || lists.size() == 0) return null;
 4         
 5         while(lists.size() > 1) {
 6             List<ListNode> newList = new ArrayList<ListNode>();
 7             for(int i = 0; i + 1< lists.size() ; i+=2) {
 8                 ListNode dummy = new ListNode(0);
 9                 dummy.next = mergeTwo(lists.get(i), lists.get(i+1));
10                 newList.add(dummy.next);
11             }
12             if(lists.size() % 2 != 0) newList.add(lists.get(lists.size() - 1));
13             lists = newList;
14         }
15         return lists.get(0);
16     }
17     
18     private ListNode mergeTwo(ListNode node1, ListNode node2) {
19         ListNode dummy = new ListNode(0), tail = dummy;
20         while(node1 != null && node2 != null) {
21             if(node1.val < node2.val) {
22                 tail.next = node1;
23                 node1 = node1.next;
24             } else {
25                 tail.next = node2;
26                 node2 = node2.next;
27             }
28             tail = tail.next;
29         }
30         if(node1 != null) {
31             tail.next = node1;
32         } else {
33             tail.next = node2;
34         }
35         return dummy.next;
36     }
37     //分治-------------------------------------------------
38      public ListNode mergeKLists(List<ListNode> lists) {  
39         if(lists == null || lists.size() == 0) return null;
40         return mergeHelper(lists, 0, lists.size() - 1);
41      }
42      private ListNode mergeHelper(List<ListNode> lists, int start , int end) {
43          if(start == end) return lists.get(start);
44          int mid = start + (end - start) / 2;
45          ListNode left = mergeHelper(lists, start, mid);
46          ListNode right = mergeHelper(lists, mid+1, end);
47          return mergeTwo(left, right);
48      }
49      
50     private ListNode mergeTwo(ListNode node1, ListNode node2) {
51         ListNode dummy = new ListNode(0), tail = dummy;
52         while(node1 != null && node2 != null) {
53             if(node1.val < node2.val) {
54                 tail.next = node1;
55                 node1 = node1.next;
56             } else {
57                 tail.next = node2;
58                 node2 = node2.next;
59             }
60             tail = tail.next;
61         }
62         if(node1 != null) {
63             tail.next = node1;
64         } else {
65             tail.next = node2;
66         }
67         return dummy.next;
68     }

View Code

11   复制随机指针链表

http://www.lintcode.com/zh-cn/problem/copy-list-with-random-pointer/#

注意点:传入head并在另一个函数中操作时,并不会引起传入前的head的变化。 

    见答案,不需要返回值  http://www.jiuzhang.com/solutions/copy-list-with-random-pointer/

九章算法_九章算法(杭州)科技有限公司

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1   public RandomListNode copyRandomList(RandomListNode head) {
 2         if(head == null) return head;
 3          head = insert(head);
 4         RandomListNode dummy = new RandomListNode(0);
 5         dummy.next = head;
 6         while(head != null) {
 7             if(head.random == null) {
 8                 head.next.random = null;
 9             } else {
10                 head.next.random = head.random.next;
11             }
12             head = head.next.next;
13         }
14         dummy.next = remove(dummy.next);
15         return dummy.next;
16         
17     }
18     private RandomListNode insert(RandomListNode head) {
19         if(head == null) return head;
20         RandomListNode dummy = new RandomListNode(0);
21         dummy.next = head;
22         while(head != null) {
23             RandomListNode temp = new RandomListNode(head.label);
24             temp.next = head.next;
25             head.next = temp;
26             head = head.next.next;
27         }
28         return dummy.next;
29     }
30     private RandomListNode remove(RandomListNode head) {
31         RandomListNode dummy = new RandomListNode(0);
32         dummy.next = head.next;
33         while(head.next.next != null) {
34             RandomListNode temp = head.next.next;
35             head.next.next = head.next.next.next;
36             head = temp;
37         }
38         return dummy.next;
39     }

View Code

 //—————————————————————————————————————–

Arrays      拿到数组先排序,最快需要nlogn.(快排,归并,堆排),然后看看排序是否有助于问题解决,是否满足复杂度要求。

    数组和的问题,排序后,收尾指针依次中间移动,可以以O(n)的代价,遍历一次就能判断是否满足。

1    合并排序数组

注意点:可以从头开始合并,也可以从尾开始合并

http://www.lintcode.com/zh-cn/problem/merge-sorted-array/

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  public void mergeSortedArray(int[] A, int m, int[] B, int n) {
 2        int index = m+n-1, i = m - 1, j = n - 1;
 3        while(i >=0 && j >=0) {
 4            if(A[i] > B[j]) {
 5                A[index--] = A[i--]; 
 6               
 7            } else {
 8                A[index--] = B[j--]; 
 9            }
10        }
11        while(i >= 0) {
12            A[index--] = A[i--]; 
13        } 
14        while(j >= 0) {
15            A[index--] = B[j--]; 
16        }
17        
18     }

View Code

 2  两个排序数组的中位数

http://www.lintcode.com/zh-cn/problem/median-of-two-sorted-arrays/

注意点:找中点,就是找第k个数,依次剔除k/2, k/4,……1个数,剩下的就是要找的数。

              如果k个排序数组找中位数,则二分答案,判断此答案是否位于中间。

错误点: 需要double,则return时除的时候要 /2.0 而不是  /2

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 //  A = 2 3 4 5 6 7
 2  //  B = 1
 3  // 找中点,第k = 4大的数,则先去掉 k/2 = 2 个数,之后再从剩下的数中找第k-k/2 = 2大的数。
 4  //                             去2个数时,由于B不包含2个数,所以把A的前2个数去掉,剩下: 4 5 6 7  和 1;  
 5  // 从它们中找第2大的数就是结果。去掉的数不一定非要是A,B中最小的前几个数,只要保证去掉的数比要找的数小,那要找的数的相对位置就不会变。
 6  // 在4 5 6 7  和 1中找第2个大的数时,先去掉1个数,在从剩下的里面找第一个大的数就是结果。所以把1去掉,剩下了4 5 6 7 。这时第1个大的数是4,也就是最后结果。
 7  
 8  public double findMedianSortedArrays(int[] A, int[] B) {
 9     int len = A.length + B.length;
10     if(len % 2 == 1) return findKth(A, 0, B, 0, len/2+1);
11     else return (findKth(A, 0, B, 0, len/2) + findKth(A, 0, B, 0, len/2+1)) / 2.0;
12 }
13 //函数含义:A数组从AStart角标开始,B从BStart开始,寻找A,B中第k个大的数
14 private int findKth(int[] A, int AStart, int[] B, int BStart, int k) {
15     if(AStart >= A.length) return B[BStart + k - 1];
16     if(BStart >= B.length) return A[AStart + k - 1];
17     
18     if(k == 1) {
19         return Math.min(A[AStart], B[BStart]);
20     }
21     
22     //找第k个,先去掉前k/2个数,AValue和BValue不可能都是MAX_VALUE
23     int AValue = AStart + k/2 - 1 < A.length ? A[AStart + k/2 - 1] : Integer.MAX_VALUE;
24     int BValue = BStart + k/2 - 1 < B.length ? B[BStart + k/2 - 1] : Integer.MAX_VALUE;
25     if(AValue <= BValue) {
26         //去A的前k/2个数,则去掉后的角标从AStart+k/2开始
27         return findKth(A, AStart+k/2, B, BStart, k - k/2);  //递归的终止条件是k-k/2=1,一定会走到1,因为1+2+...+ k/2 = k - 1 k是偶数,1+1+2+...+ k/2 = k - 1 k是奇数
28     } else {
29         return findKth(A, AStart, B, BStart + k/2, k - k/2);
30     }
31 }

View Code

3  最大子数组2

http://www.lintcode.com/zh-cn/problem/maximum-subarray-ii/

衍生:最小子数组  http://www.lintcode.com/zh-cn/problem/minimum-subarray/#   把数组取反,求出最大子数组,再把结果取反即可。

   最大子数组差   http://www.lintcode.com/zh-cn/problem/maximum-subarray-difference/  左右求出最大最小子数组,因为不许重叠,所以找分割线依次比较。

错误点:a=1,b=2;错,要写成a=1;b=2;

    int a =1, b = 2; 可以

注意点:见答案

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 //最大子数组答案    http://www.lintcode.com/zh-cn/problem/maximum-subarray/   
 2  public int maxSubArray(int[] nums) {
 3     if(nums == null || nums.length == 0) return 0;
 4     int sum = 0, preFixSum = 0, max = Integer.MIN_VALUE;
 5     //理解不了的话,只需要知道这个操作能实现功能就行,死记代码
 6     for(int i = 0; i< nums.length; i++) {
 7         sum+= nums[i];
 8         max = Math.max(max, sum - preFixSum);
 9         preFixSum = Math.min(preFixSum, sum);
10     }
11     return max;
12  }
13  
14  public int maxTwoSubArrays(List<Integer> nums) {
15      if(nums == null || nums.size() <= 1) return 0;
16      // i是分割线位置,i+1就是分割线之后的第一个位置的坐标
17      int result = Integer.MIN_VALUE;
18      for(int i = 0; i < nums.size() - 1; i++) {
19          int max1 = Integer.MIN_VALUE, max2 = max1;
20          int sum1 = 0, sum2 = 0, preFix1 = 0, preFix2 = 0;
21          for(int j = 0; j <=i; j++) {
22              sum1+=nums.get(j);
23              max1 = Math.max(max1, sum1 - preFix1);
24              preFix1 = Math.min(preFix1, sum1);
25          }
26          for(int j = i+1; j < nums.size(); j++) {
27              sum2+=nums.get(j);
28              max2 = Math.max(max2, sum2 - preFix2);
29              preFix1 = Math.min(preFix2, sum2);
30          }
31          result = Math.max(result, max1+max2);
32      }
33      return result;
34  }
35  //O(n)---------------------------------------------
36   public int maxTwoSubArrays(List<Integer> nums) {
37       int[] left = new int[nums.size()];
38       int[] right = new int[nums.size()];
39       int sum = 0, preFixSum = 0, max = Integer.MIN_VALUE;
40       for(int i = 0; i< nums.size(); i++) {
41           sum+= nums[i];
42           max = Math.max(max, sum - preFixSum);
43           preFixSum = Math.min(preFixSum, sum);
44           left[i] = max;
45       }
46       sum = 0, preFixSum = 0, max = Integer.MIN_VALUE;
47       for(int i = nums.size() - 1; i >= 0; i--) {
48           sum+= nums[i];
49           max = Math.max(max, sum - preFixSum);
50           preFixSum = Math.min(preFixSum, sum);
51           right[i] = max;
52       }
53       int result = Integer.MIN_VALUE;
54       for(int i = 0; i < nums.size() - 1; i++) {
55           result = Math.max(result, left[i] + right[i+1]);
56       }
57       return result;
58   }

View Code

4  买卖股票的最佳时机

http://www.lintcode.com/zh-cn/problem/best-time-to-buy-and-sell-stock/

http://www.lintcode.com/zh-cn/problem/best-time-to-buy-and-sell-stock-ii/

http://www.lintcode.com/zh-cn/problem/best-time-to-buy-and-sell-stock-iii/#

 注意点:包含DP

错误点:  ①profit = Math.max(profit, i – min);

           ②min = Math.min(min, i);            一二前后顺序的区别是是否每一轮至少要包含一个数。此题中盈利的计算,一开始是买入,没有盈利,所以也即一个数都不能包含,

                   所以要先②后①。

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 //错误逻辑,思路都理不清,代码更写不出来。 
 2  public int maxProfit(int[] prices) {
 3     if(prices == null || prices.length <= 1) return 0;
 4     int profit = 0, min = 0;
 5     for(int i : prices) {
 6         min = Math.min(min, i);
 7         profit + =  i - min;    
 8     }
 9     return profit;
10 }
11 // 当天有盈利,代表着当天卖出和前一天买入。连续三天盈利,每隔天的买入卖出正好合下来是三天前买入,三天后卖出的情况。 1    2    3    4
12 public int maxProfit(int[] prices) {
13     int profit = 0;
14     for(int i = 0; i < prices.length- 1; i++) {
15         int diff = prices[i + 1] - prices[i];
16         if(diff > 0) profit += diff;
17     }
18     return profit;
19 }

update1

 

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  //-----------------------------------------------------------
 2     //  暴力激活成功教程
 3      public int maxProfit(int[] prices) { 
 4         if(prices == null || prices.length == 0) return 0;
 5         int max =0 ;
 6         for(int i = 1; i< prices.length; i++) {
 7             int sum = 0;
 8             for(int j = 0; j < i; j++) {            
 9                 max= Math.max(max, prices[i] - prices[j]);
10             }            
11         }
12         return max;
13    }
14  //------------------------------------------------------
15    public int maxProfit(int[] prices) { 
16       if(prices == null || prices.length == 0) return 0;
17       int min = Integer.MAX_VALUE, profit = 0;
18       for(int i : prices) {
19           min = Math.min(i, min);   // min = i < min ? i : min;
20           profit = Math.max(i - min, profit);
21       }
22       return profit;
23    }
24    
25 //股票二------------------------------------------
26 public int maxProfit(int[] prices) {
27     int profit = 0;
28     for(int i = 0; i < prices.length- 1; i++) {
29         int diff = prices[i + 1] - prices[i];
30         if(diff > 0) profit += diff;
31     }
32     return profit;
33 }
34 
35 //股票三-----------------------------------------------
36 public int maxProfit(int[] prices) {
37     if (prices == null || prices.length <= 1) {
38             return 0;
39         }
40 
41     int[] left = int[prices.length];
42     int[] right = int[prices.length];
43     
44     //从左往右看,不依赖于右侧,能卖出的最大利润。通过更新买入的最小值(min)来计算  DP
45     int min = prices[0], left[0] = 0;
46     for(int i = 1; i < prices.length; i++) {
47         min = math.min(min, prices[i]);
48         left[i] = Math.max(left[i - 1], prices[i] - min);
49     }
50     
51     //从右往左看,不依赖于左侧,能卖出的最大利润。通过更新卖出的最大值(max)来计算
52     int max = prices[prices.length - 1], right[prices.length - 1] = 0;
53     for(int i = prices.length -2; i>=0; i--) {
54         max = Math.max(prices[i], max);
55         right[i] = Math.max(right[i + 1], max - prices[i]);
56     }
57     
58     //类似分割线,left和right不交叉
59     int maxProfit = 0;
60     for(int i = 0; i < prices.length; i++) {
61         maxProfit = Math.max(maxProfit, left[i] + right[i]);
62     }
63     return maxProfit;
64 }

View Code

 5  两数和

http://www.lintcode.com/zh-cn/problem/two-sum/

衍生: 三数和  http://www.lintcode.com/zh-cn/problem/3sum/ 

    4数    http://www.lintcode.com/zh-cn/problem/4sum/ 

注意点:时间复杂度的计算:

      排序模块的最优复杂度nlogn,找两数和的复杂度n,所以合并的复杂度是nlogn,即用这种方法的复杂度为nlogn。

      如果放入map中,遍历一次数组,复杂度n,判断map是否包含,n,所以最后合并的复杂度n。

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 //O(n * n)---------------------------------------------------------------
 2  public int[] twoSum(int[] numbers, int target) { 
 3     if(numbers == null || numbers.length == 0) return new int[]{-1, -1};
 4     for(int i = 0; i < numbers.length - 1; i++) {
 5         for(int j = i +1; j < numbers.length; j++) {
 6             if(numbers[i] + numbers[j] == target) return new int[]{i +1, j+1};
 7         }
 8     }
 9     return new int[]{-1, -1};
10     
11  //O(nlogn)--------------------------
12 public int[] twoSum(int[] numbers, int target) { 
13     //先排序,获得排序数组nlogn,下面的操作是O(n),最后总体的时间复杂度nlogn.
14     if(numbers == null || numbers.length <=1) return new int[]{-1, -1};
15     for(int i = 0, j = numbers.length - 1; i < j;) {
16         if(numbers[i] + numbers[j] == target) return new int[]{i + 1,j + 1};
17         else if ( numbers[i] + numbers[j] < target) i++;
18         else j--;
19     }
20     return new int[]{-1, -1};
21 
22 }
23 //O(n)------------------------------
24 public int[] twoSum(int[] numbers, int target) { 
25     if(numbers == null || numbers.length == 0) return null;
26     Map<Integer, Integer> map = new HashMap<Integer, Integer>();
27     for(int i = 0; i < numbers.length; i++) {    
28         if(map.containsKey(numbers[i])) {
29             return new int[] {map.get(numbers[i]) + 1, i+1};
30         }
31         map.put(target - numbers[i], i);
32     }
33     return null;

View Code

 6  数组划分 (类似快排)

http://www.lintcode.com/zh-cn/problem/partition-array/#

衍生:  http://www.lintcode.com/zh-cn/problem/sort-letters-by-case/        Character.isUpperCase()  

     http://www.lintcode.com/zh-cn/problem/sort-colors/  

     http://www.lintcode.com/zh-cn/problem/sort-colors-ii/    (相当于给定k个不同的数的快排)

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 //报错,rainb里不设置startColo会排序出问题,所以这种换位的快排操作到底会产生什么结果?----------------------------------------------
 2 public void sortColors2(int[] colors, int k) {
 3      if (colors == null || colors.length == 0) {
 4             return;
 5         }
 6     rainbowSort(colors, 0, colors.length - 1);
 7 
 8 }
 9     
10 private void rainbowSort(int[] colors, int start, int end) {
11     if(colors == null || colors.length <= 1) return;
12     if(start >= end) return;
13     int mid = start + (end - start) / 2;
14     int k = colors[mid];
15     int i = start, j = end;
16     while(i <= j) {
17         while(i <=j && colors[i] < k) i++;
18         while(i <=j && colors[j] >= k) j--;
19         if(i <= j) {
20             int temp = colors[i];
21             colors[i] = colors[j];
22             colors[j] = temp;
23             i++;
24             j--;
25         }
26     }
27     rainbowSort(colors, start, i - 1);
28     rainbowSort(colors,i + 1, end);
29 } 
30 //能用--------------------------------------------------------------------------------- 
31  public void sortColors2(int[] colors, int k) {
32      if (colors == null || colors.length == 0) {
33             return;
34         }
35     rainbowSort(colors, 0, colors.length - 1, 1,k);
36 
37 }
38     
39 private void rainbowSort(int[] colors, int start, int end, int startColor, int endColor) {
40      if (startColor == endColor) {
41             return;
42         }
43     if(colors == null || colors.length <= 1) return;
44     if(start >= end) return;
45     int midColor = (startColor + endColor)/2;
46     int i = start, j = end;
47     while(i <= j) {
48         //为啥??????????????
49         //这里必须 <= midColor, 不能是<
50         while(i <=j && colors[i] <=  midColor) i++;
51         while(i <=j && colors[j] >  midColor) j--;
52         if(i <= j) {
53             int temp = colors[i];
54             colors[i] = colors[j];
55             colors[j] = temp;
56             i++;
57             j--;
58         }
59     }
60     //这里必须是midColor,不能是midColor+1
61     rainbowSort(colors, start, i, startColor,  midColor);
62     rainbowSort(colors,i,end,  midColor+1, endColor);
63 }

sort color 2

注意点: 两个指针一首一尾遍历数组        

    死记住程序,条件统一写成 i <= j  :这样返回的 i 始终是第一个大于等于k的位置,也正是题目所求。

    if(i <= j) 调制完顺序后,i++,j–一下,减少下一次while里的操作。

九章算法_九章算法(杭州)科技有限公司数组划分
九章算法_九章算法(杭州)科技有限公司

 1   public int partitionArray(int[] nums, int k) {
 2         if(nums == null | nums.length <= 0) return -1;
 3         int i = 0, j = nums.length - 1;
 4         while(i <= j) {
 5             while(nums[i] < k) i++;
 6             while(nums[j] >= k) j--;
 7             if(i <= j) {
 8                 int temp = nums[j];
 9                 nums[j] = nums[i];
10                 nums[i] = temp;
11             }
12         }
13         return i;
14    }


 7 最接近零的子数组和

http://www.lintcode.com/en/problem/subarray-sum-closest/

问题:最后利用减前缀和求结果的时候,怎么知道这样的结果就离0最近? 难道是因为后一个肯定比前一个大,所以相减的结果一定大于0,最小的那个就是最接近0的?确实是这样。

      -1,-3, -3,-2,1,4,;

 -1位置补0     -1,-3, -3,-2,1,4,   前缀和    -1,-4,-7,-9,-8,-4,排序后:-9,-8,-7,-4,-4,-1。

 子数组一共有O(n * n)个,这里两两相减也就O(n)个,不能全覆盖啊?

注意点:  实现Comparator比较器接口时,虽然接口中有俩抽象方法,但只需要实现compare方法就行,equals方法不用覆盖。

     此题对应的解法,在数组中有0时,会返回两次0的角标作为返回结果。

错误点: new int[]{0,1}  ,不要写错new int[2]{}

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  class Pair {
 2      //记录前几个数的和
 3      int sum;
 4      int index;
 5      public Pair(int s, int i) {
 6          this.sum = s;
 7          this.index = i;
 8      }
 9  }
10  
11  public class Solution {
12  
13      public int[] subarraySumClosest(int[] nums) { 
14         if(nums == null || nums.length == 0) return null;
15         if(nums.length == 1) return new int[]{0, 0};
16         //结果集数组
17         int[] res = new int[2];
18         
19         int len = nums.length;
20         //遍历一次nums,获得Pair数组,其中,前0个数的和是0
21         Pair[] sums = new Pair[len + 1]; 
22         sums[0] = new Pair(0,0);
23         for(int i = 1; i <= len; i++) {
24             sums[i] = new Pair(sums[i - 1].sum + nums[i - 1], i);
25         }
26         
27         Arrays.sort(sums, new  Comparator<Pair>(){
28             public int compare(Pair p1, Pair p2) {
29                 return p1.sum - p2.sum;
30             }
31         });
32         
33         //排序完成后,遍历sums数组,找到离0最近的子数组,从角标1开始。
34         int ans = Integer.MAX_VALUE; //answer
35         for(int i = 1; i <= len; i++) {
36             if(ans > sums[i].sum - sums[i - 1].sum) { 
37                 ans = sums[i].sum - sums[i - 1].sum;
38                 //Pair 记录的是前几个数的和,前0,1,2个等等,对应nums中的角标需要-1;
39                 int[] temp = new int[]{sums[i].index - 1, sums[i - 1].index - 1};
40                 Arrays.sort(temp);
41                 //前5个数的和-前3个数的和离0最近,则需要返回的是第4,第5个的角标,所以temp[0]+1;
42                 res[0] = temp[0] + 1; 
43                 res[1] = temp[1];
44             }
45         }
46         return res;
47      }
48  }

View Code

 8 子数组之和(求子数组,先写出来前缀和,sum(i,j) = sum(j) – sum(i – 1),然后看它和所求的关系)

http://www.lintcode.com/zh-cn/problem/subarray-sum/

注意点:子数组和为0,代表存在位置,sum(j) 等于sum(i-1)。

       既然需要sum(i – 1),那为了求0位置的和同时能用到上面的递推关系,所以在-1位置放一个0;

      两sum相等,相当于去重,hash表天然就是实现是否存在,相等问题的,所以使用hashMap存放数据。

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public ArrayList<Integer> subarraySum(int[] nums) {
 2       if(nums == null || nums.length == 0) return null;
 3       ArrayList<Integer> res = new ArrayList<Integer>();
 4       Map<Integer, Integer> map = new HashMap();
 5       map.put(0, -1);
 6       int sum = 0;
 7       for(int i = 0; i < nums.length; i++) {
 8           sum += nums[i];
 9           if(map.get(sum) != null) {
10               res.add(map.get(sum) + 1);
11               res.add(i);
12               return res;
13           }
14           map.put(sum, i);
15       }
16       return null;
17   }

View Code

 

数据结构

1 带最小值操作的栈

http://www.lintcode.com/zh-cn/problem/min-stack/#

注意点: 用另一个栈依次记录最小值。

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public class MinStack {
 2  
 3     //minStack的构造放到构造函数中比较好。
 4    Stack<Integer> minStack = new Stack<Integer>();
 5    Stack<Integer> s ;
 6     
 7     public MinStack() {
 8         // do initialize if necessary
 9        s = new Stack<Integer>();
10     }
11 
12     public void push(int number) {
13         // write your code here
14         s.push(number);
15         if(minStack.isEmpty() || minStack.peek() >= number) minStack.push(number);
16     }
17 
18     public int pop() {
19         // write your code here
20         int number = s.pop();
21         if(number == minStack.peek()) minStack.pop();
22         return number;
23     }
24 
25     public int min() {
26         // write your code here
27         
28         return minStack.peek();
29     }
30 }

View Code

 

2 用栈实现队列 

http://www.lintcode.com/zh-cn/problem/implement-queue-by-two-stacks/#

3 直方图最大矩形覆盖(栈)

http://www.lintcode.com/zh-cn/problem/largest-rectangle-in-histogram/#

注意点: 递增栈,每次角标出栈时才计算对应角标高度的直方图面积。(while循环里,栈内弹出一个数需要O(1),弹出n个数需要O(n),所以while的平均时间为O(1),所以

    总体时间就只是for的时间,O(n))。

    高度中找左边和右边第一个比他小的位置,然后就是此高度对应的宽度。

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  public int largestRectangleArea(int[] height) {
 2      if(height == null || height.length == 0) return 0;
 3      Stack<Integer> s = new Stack<Integer>();
 4      int max = 0;
 5      for(int i = 0; i <= height.length; i++) {
 6          int currHeight = (i == height.length)?-1:height[i];
 7          while(!s.isEmpty() && currHeight <= height[s.peek()]) {
 8              int h = height[s.pop()];
 9              int w = s.isEmpty()? i: i - s.peek() - 1;
10              max = Math.max(max, h*w);
11          }
12          s.push(i);
13      }
14      return max;
15  }

View Code

 九章算法_九章算法(杭州)科技有限公司

4 哈希表原理(增删查的复杂度O(1),二叉查找树logn)

Cache (一个大的哈希表):memory级别的访问, ns级别,500M/b
数据库:文件系统访问,硬盘,微秒级别,500k/b

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public void hashFunc(String key) {
 2       //hash本身就是杂乱无章的表示。所以不要去理解表达的含义,大概类似于把key按33进制表示出来,同时让他最后的值处于HASH_TABLE_SIZE的范围中。
 3       int sum = 0;
 4       for(int i = 0; i < key.length(); i++ ) {
 5           sum = sum * 33 + (int)key.charAt(i);
 6           sum = sum % HASH_TABLE_SIZE;  //如果不包含这一步,则相当于把key当成33进制数表示出来。   1234 按十进制表达: ((1*10 + 2)*10+3)*10 + 4;      
 7                                         //HASH_TABLE_SIZE 表示开辟的数组大小,实际存储的数据size/HASH_TABLE_SIZE = 1/10 最好,否则size再大,
 8                                         //产生冲突的概率会增大。每一次操作都保证sum在HASH_TABLE_SIZE的范围内。
 9     
10       }
11       return sum;
12   }    

View Code

5 重哈希(需要把所有的数重新计算插入一遍,很麻烦,所以尽量避免重哈希的出现,开始定义hash大小时数组开的空间大点。)

http://www.lintcode.com/zh-cn/problem/rehashing/

注意点: 增加链表时,一定要new,而且是· .next = new ListNode,不然赋值不过来。不知道地址传递到底是怎么传的。

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  public ListNode[] rehashing(ListNode[] hashTable) {
 2         if(hashTable == null || hashTable.length == 0) return hashTable;
 3         ListNode[] newHash = new ListNode[hashTable.length * 2];
 4         int len = newHash.length;
 5         for(int i = 0; i < hashTable.length; i++) {
 6             ListNode node = hashTable[i];
 7             int index = 0;
 8             while(node != null ) {
 9                  index = (node.val%len + len) % len;
10                  if(newHash[index] == null) {
11                      newHash[index] = new ListNode(node.val);
12                      node = node.next;
13                      continue;
14                  } 
15                  ListNode head = newHash[index];
16                  while( head.next != null) {
17                      head = head.next;
18                  }
19                 head = new ListNode(node.val);
20           
21                 node = node.next;
22             }
23         }
24         return newHash;
25     }

View Code

 6 快乐数(hash)

http://www.lintcode.com/zh-cn/problem/happy-number/

注意点: 注意按位取元素的方法

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 private int getNextHappy(int n) {
 2         int sum = 0;
 3         while (n != 0) {
 4             sum += (n % 10) * (n % 10);
 5             n /= 10;
 6         }
 7         return sum;
 8     }
 9     
10     public boolean isHappy(int n) {
11         HashSet<Integer> hash = new HashSet<Integer>();
12         while (n != 1) {
13             if (hash.contains(n)) {
14                 return false;
15             }
16             hash.add(n);
17             n = getNextHappy(n);
18         }
19         return true;
20     }

View Code

 7 LRU缓存策略

http://www.lintcode.com/zh-cn/problem/lru-cache/

注意点: node结点写在主类里面,因为它只需要在此类里暴露,不需要对外显示。

     一共有两种存储的数据结构,map存放指定容量的key,value数据,LinkedList存放各种数据的前后放入关系。所以操作数据时,要同时维护这两种数据结构,get方法只需要维护链表,set方法两个都需要维护。

(堆相关)

 8 数据流中位数    优先队列/heap :O(log N) Add    O(log N) Remove   O(1) Min/Max    二叉树实现的,根节点是最值,每次移除根节点,都需要从剩下的结点中找到最值

          再移到根上,所以remove是O(logn)。堆排序只能保证根是最大(最小),不能保证整体是按照顺序来排序的。

http://www.lintcode.com/zh-cn/problem/data-stream-median/ 

注意点: offer  poll方法

    maxHeap里存放小于等于中位数的数字,minHeap里放大于中位数的数字。 中位数,则 maxHeap.size() == minHeap.size() 或者maxHeap.size() == minHeap.size()+1

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  public int[] medianII(int[] nums) {
 2         // write your code here  
 3     if(nums == null || nums.length == 0) return null;
 4     PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
 5     PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(1, new Comparator<Integer>(){
 6         //@Override   可以不写,但是compare方法参数必须是Integer,不能是int
 7         public int compare(Integer x, Integer y) {
 8             return y - x;
 9         }
10     });
11     int[] res = new int[nums.length];
12     res[0] = nums[0];
13     maxHeap.offer(nums[0]);
14     for(int i = 1; i < nums.length; i++) {
15         if(nums[i] <= maxHeap.peek()) {
16             maxHeap.offer(nums[i]);
17         } else {
18             minHeap.offer(nums[i]);
19         }
20         
21         //开始进入两个元素时,size上,maxHeap = minHeap 或者 maxHeap = minHeap +2,经过下面的if语句,转变成maxHeap = minHeap 
22         // 每一轮进来后,只会出现maxHeap = minHeap 或者maxHeap = minHeap +1两种情况。(类似一种递推的关系)
23         if(maxHeap.size() > minHeap.size() + 1) {
24             minHeap.offer(maxHeap.poll());
25         } else if( maxHeap.size() < minHeap.size()) {
26             maxHeap.offer(minHeap.poll());
27         } 
28         res[i] = maxHeap.peek();
29     }
30     return res;    
31 }

View Code

 9 堆化  (有点堆排序的意思)

http://www.lintcode.com/zh-cn/problem/heapify/

注意点:    0         1          2      3      4      5     6      原序列

    1   2      3       4       5      6            原序列元素对应的子树角标。

    A[0]肯定是最小值。

     siftdown的O(n)遍历方式很独特,从中间开始遍历。

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 //   0 1 2 3 4 5 6 7  len = 8,   mid = 3     对于位置i,两个子树2i+1,2i+2;对于位置i-1,子树2(i-1) +1, 2(i-1) +2,即2i-1和2i。
 2                                              //也就是说 i-1,i-1恰好能连续覆盖掉2i-1,2i,2i+1,2i+2;
 3  //   0 1 2 3 4 5 6 7 8  len = 9, mid = 4
 4  
 5     public void heapify(int[] A) {
 6         // write your code here
 7         //O(n)完成,只遍历一次,但是遍历的方式不是简单的从头到尾,而是从中间往左。
 8         int mid = (A.length - 1)/2;
 9         for(int i = mid; i >=0; i--) {
10             siftdown(A, i);
11         }
12         
13     }
14     
15     private void siftdown(int[] A, int k) {
16         int son = 0;
17         while(2*k+1 < A.length) {   //从后往前保证 两个子树比根小,即有一定顺序。如果靠前的位置发生过swap,那也要保证swap之后,后面的位置还是有序
18                                     //所以有k = son
19             son = 2*k+1;
20             if(2*k+2 < A.length && A[2*k+2] <= A[son] ) son = 2*k+2; //son是两个子树中的较小的一个
21             
22             if(A[son] < A[k]) {
23                 swap(A, son, k);
24                 k = son;
25             } else {
26                 break;
27             }
28         }
29         
30     }
31     private void swap(int[] A, int x, int y) {
32         int temp = A[x];
33         A[x] = A[y];
34         A[y] = temp;
35     }

View Code

 10 丑数

http://www.lintcode.com/zh-cn/problem/ugly-number/

http://www.lintcode.com/zh-cn/problem/ugly-number-ii/#

注意点: 不理解丑数2的话看代码里的解释。

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1  public int nthUglyNumber(int n) {
 2      int[] uglyArr = new int[n];
 3      uglyArr[0] = 1;
 4      //p2,p3,p5代表三个指针,指向uglyArr数组的索引。
 5      int p2 = 0, p3=0, p5 = 0;
 6      for(int i= 1; i < n; i++) {
 7          //  <= 说明此索引位置的丑数已经乘以过2了,即已有的丑数数组中已经包含由此位置丑数*2所对应的丑数了,
 8          //  那么下一轮再乘的时候,就不能用此位置的丑数*2了,要用下一个丑数来乘。
 9          //  所以p2表示:当前待乘以2来候选作为下一个丑数的数的角标
10          //为啥不是用uglyArr[i - 1]来乘2呢,比如1, 2,,3 用 3 *2 显然比 2* 2大,所以下一个丑数不是3*2。
11          //所以应该记录的是之前的丑数,1,2,3是否乘过2,3,5,p2= 1,p3= 1, p5 = 0表示5还没有乘过角标0的数,2没有乘过角标1的数,3没有乘过角标1的数。
12          if(uglyArr[p2] * 2 <= uglyArr[i - 1]) p2++;
13          if(uglyArr[p3] * 3 <= uglyArr[i - 1]) p3++;
14          if(uglyArr[p5] * 5 <= uglyArr[i - 1]) p5++;
15          
16          //这一轮最小值是乘的2,3还是5会在下一轮通过if判断出来,判断出来后,p2,p3,p5中有且只有一个指针会移动1个位置。
17          uglyArr[i] = Math.min(uglyArr[p2] * 2, 
18                         Math.min(uglyArr[p3] * 3, uglyArr[p5] * 5));
19      }
20      return uglyArr[n - 1];
21  }

View Code

 11.字符串查找

http://www.lintcode.com/zh-cn/problem/strstr/

注意点: O(n)实现 Rabin-Karp算法

  1234  : 234=10(123-100)+4 = 123*10+4-1000 此处用的是后面的计算方式

  (a+b)%b= (a%b+b%b)%b= a%b  这正是当hashcode<0时采取的做法,也就是对它取模,hashcode%HASH_SIZE=(hashcode+HASH_SIZE)%HASH_SIZE

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 /** 验证下面的结论是否普遍成立:
 2      *     1%11*10%11*10%11=100%11=1  power
 3      *     5%11*10%11*10%11= 5    =1 * 5 
 4      *  结论是:成立
 5      */
 6     public static void main(String[] args) {
 7         int HASH_SIZE=1000000;
 8         for(int numberSize = 2; numberSize < 10; numberSize++) {
 9             int power = 1;
10             for(int i = 0; i <4; i++) {
11                 power = (power*31)%HASH_SIZE;
12             }
13             for(int i =1; i < 10; i++) {
14                 int count = 0;
15                 int num = i;
16                 int count0 = (num* power)%HASH_SIZE;
17                 for(int j = 0; j < 5; j++) {
18                     if(j != 0) num = 0;
19                     count = (count*31+num)%HASH_SIZE;
20                 }
21                 if(count != count0){
22                     System.out.println(i);
23                     break;
24                 }
25             }
26             System.out.println(numberSize+"::finish");
27         }
28     }

验证

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 private int HASH_SIZE = 1000000;
 2 
 3     public int strStr(String source, String target) {
 4         // Write your code here
 5         if (source == null || target == null) {
 6             return -1;
 7         }
 8         int m = source.length();
 9         int n = target.length();
10         if (n == 0) {
11             return 0;
12         }
13         if (m == 0) {
14             return -1;
15         }
16         int targetCode = 0;
17         for (int i = 0; i < n; i++) {
18             targetCode = (targetCode * 31 + target.charAt(i)) % HASH_SIZE;
19         }
20         int power = 1;
21         for (int i = 0; i < n; i++) {
22             power = (power * 31) % HASH_SIZE;
23         }
24         int hashCode = 0;
25         for (int i = 0; i < m; i++) {
26             //只有一开始i = n-1 时hashCode记录的是n个数的hash值,
27             //之后一直记录的是n+1个数的值,所以power才要乘31^n 而不是31^(n-1)
28             hashCode = (hashCode * 31 + source.charAt(i)) % HASH_SIZE;
29             if (i < n - 1) {
30                 continue;
31             }
32             if (i >= n) {
33                 hashCode = hashCode - (source.charAt(i - n) * power)% HASH_SIZE ;
34                 //为啥可能出现hashcode<0? 因为新添加的一位导致hashcode的值>HASH_SIZE,出现了取模的情况,
35                 // 而 a%b = (a+b)%b,所以<0的情况,原本的hashcode计算方式应该是:
36                 // hashcode = hashCode + HASH_SIZE - (source.charAt(i - n) * power)% HASH_SIZE ;
37                 // 所以如果遇到<0的情况,加HASH_SIZE就好了。
38                 if (hashCode < 0) {
39                     hashCode += HASH_SIZE;
40                 }
41             }
42             // 0~n-1  i=n-1, 0 = i - n+1
43             // 1~n    i=n,   1 = i - n+1
44             if (hashCode == targetCode) {
45                 if (source.substring(i - n + 1, i + 1).equals(target)) {
46                     return i - n + 1;
47                 }
48 
49             }
50         }
51         return -1;
52     }

View Code

 九章算法_九章算法(杭州)科技有限公司

 

graph and search

1 克隆图

http://www.lintcode.com/zh-cn/problem/clone-graph/#

拓扑排序

http://www.lintcode.com/zh-cn/problem/topological-sorting/#

注意点:图肯定要用hashMap

    遍历完图的方式:while(start < res.size()) { start++}   res动态增长,size变化,所有结点都加入进去后,就不变了,而start也增长,实现遍历完全的目的。

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
 2         //图的BFS,类似二叉树的BFS,不过需要统计邻居关系,避免已经访问过的邻居重复访问,所以用Map+ Queue实现。
 3         //Queue可以用ArrayList + 头索引的位置来表示
 4         if(node == null) return node;
 5         ArrayList<UndirectedGraphNode> list = new ArrayList();  //放原先的结点
 6         Map<UndirectedGraphNode,UndirectedGraphNode> map = new HashMap();  //放复制节点和原先结点的映射关系
 7         int start = 0;
 8         
 9         list.add(node);
10         map.put(node, new UndirectedGraphNode(node.label));
11         while(start < list.size()) {
12             UndirectedGraphNode curr = list.get(start++);
13             for(int i = 0; i < curr.neighbors.size(); i++) {
14                 if(!map.containsKey(curr.neighbors.get(i))) {
15                     list.add(curr.neighbors.get(i));
16                     map.put(curr.neighbors.get(i), new UndirectedGraphNode(curr.neighbors.get(i).label));
17                 }
18             }
19         }
20         
21         // copy edge
22         for(int i = 0; i < list.size(); i++) {
23             UndirectedGraphNode curr = list.get(i);
24             for(int j = 0; j < curr.neighbors.size(); j++) {
25                 map.get(curr).neighbors.add(map.get(curr.neighbors.get(j)));
26             }
27         }
28         return map.get(node);
29     }

View Code

 2 全排列(DFS)

http://www.lintcode.com/zh-cn/problem/permutations/

http://www.lintcode.com/zh-cn/problem/subsets/   子集

http://www.lintcode.com/zh-cn/problem/subsets-ii/#

http://www.lintcode.com/zh-cn/problem/permutations-ii/#

http://www.lintcode.com/zh-cn/problem/combination-sum/#     list里add一个元素,再做dfs,然后再remove掉

注意点: 写递归,想清楚两件事:

            1.递归是做了一件什么样的事情,和参数的关系是什么

            2.想清楚递归在什么时候return

            3.想清楚递归关系,把大问题化解成小问题解决。

错误点:  返回  List<List<Integer>>,则声明为:List<List<Integer>> rst = new ArrayList<List<Integer>>();    List<Integer> list = new ArrayList<Integer>();

    返回ArrayList<ArrayList<Integer>>,  声明为:ArrayList<ArrayList<Integer>> rst = new ArrayList<ArrayList<Integer>>();

                         ArrayList<Integer> list = new ArrayList<Integer>();   按上面的声明无法通过编译

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public List<List<Integer>> permute(int[] nums) {
 2     // write your code here
 3     if(nums == null) return null;
 4     List<List<Integer>> rst = new ArrayList<List<Integer>>();
 5     ArrayList<Integer> list = new ArrayList<Integer>();
 6     if(nums.length == 0) {
 7         rst.add(list);
 8         return rst;
 9     }
10     helper(rst, list, nums );
11     return rst;
12 }
13 
14 public void helper(List<List<Integer>> rst, ArrayList<Integer> list, int[] nums){
15     if(list.size() == nums.length) {
16         //不能rst.add(list) 地址传递,最后内容都没了
17         rst.add(new ArrayList<Integer>(list));
18         return;
19     }
20     for(int i = 0; i < nums.length; i++) {    //假设nums={1,2,3,4},最外的循环进来,for4次对应四种情况:     [ ]
21                                               //                                                                |--[1]
22                                               //                                                                |--[2]
23                                               //                                                                |--[3]
24                                               //                                                                |--[4]
25                                               //对于每一种情况,比如[1],又分为了三种  [1]
26                                               //                                         |--[2]
27                                               //                                         |--[3]
28                                               //                                         |--[4]
29                                               //......最后直到list.size()==nums.length,所有元素都放进去了,才作为一次结果返回。
30         
31         if(list.contains(nums[i])) {
32             continue;
33         }
34         list.add(nums[i]);
35         helper(rst, list, nums);
36         list.remove(list.size() - 1);
37     }
38 }

View Code

3 N皇后问题

http://www.lintcode.com/zh-cn/problem/n-queens/#

注意点:分成4块,每块函数各司其职

错误点:     (cols.get(i) == j)?sb.append(‘Q’):sb.append(‘.’); (错)     sb.append(j == cols.get(i) ? ‘Q’ : ‘.’);(对)  三目表达式,一个整体

九章算法_九章算法(杭州)科技有限公司九章算法_九章算法(杭州)科技有限公司

 1  ArrayList<ArrayList<String>> solveNQueens(int n) {
 2     if(n <= 0) return null;
 3     ArrayList<ArrayList<String>> rst = new ArrayList<ArrayList<String>>();
 4     search(rst, new ArrayList<Integer>(), n);
 5     return rst;
 6         
 7  }
 8 
 9  private void search(ArrayList<ArrayList<String>> rst, ArrayList<Integer> cols, int n) {
10      if(cols.size() == n) {
11          rst.add(drawChess(cols));
12          return;
13      }
14      for(int i = 0; i < n; i++) {
15          if(!isValid(cols, i)) {
16             continue; 
17          }
18          cols.add(i);
19          search(rst, cols, n);
20          cols.remove(cols.size() - 1);
21      }
22  }
23  //查看第cols.size()行的第colIndex 列是否合法
24  //根据cols元素的放法的定义,不可能出现同一行,只可能有同一列或者同一斜行的情况。
25  private boolean isValid(ArrayList<Integer> cols, int colIndex) {
26      int rowIndex = cols.size();
27      for(int i = 0; i < rowIndex; i++) {
28          if(cols.get(i) == colIndex) return false;
29          // right-top  to left-down
30         // 。Q 。 。
31         // 。。 Q  。   左上到右下情况下的相同斜线:  (0, 1)  (1,2)  行序号-列序号的值相等。
32         
33         // 。。 。 Q
34         // 。。 Q  。   右上到左下情况下的相同斜线:  (0, 3)  (1,2)  行序号+列序号的值相等。
35          if(cols.get(i) + i == rowIndex + colIndex) return false;
36          if(cols.get(i) - i == colIndex - rowIndex ) return false;
37      }
38      return true;
39  }
40  private ArrayList<String> drawChess(ArrayList<Integer> cols) {
41      ArrayList<String> list = new ArrayList<String>();
42      for(int i = 0; i < cols.size(); i++) {
43          StringBuilder sb = new StringBuilder();
44         for(int j = 0; j < cols.size(); j++) {
45             //(cols.get(i) == j)?sb.append('Q'):sb.append('.');
46             sb.append(j == cols.get(i) ? 'Q' : '.');
47         }
48         list.add(sb.toString());
49      }
50      return list;
51  }

View Code

4 单词接龙

http://www.lintcode.com/zh-cn/problem/word-ladder/      BFS   找最短路

http://www.lintcode.com/zh-cn/problem/word-ladder-ii/#    找所有方案,需要DFS,同时也要找最短路对应的所有方案,所以是DFS+BFS

注意点: BFS,因为每次只变一步,可以画出一张单词变化图出来, lot-log-pog  

    第一种方法超时了,差别主要在找下一个合法单词的方式上,一种是遍历dict,依次判断每个单词是否是合法的单词,另一种是先写出当前单词的所有的合法

    改变单词来,然后判断它是否在dict中。结果是第二种方式更优,为啥??

九章算法_九章算法(杭州)科技有限公司九章算法_九章算法(杭州)科技有限公司

  1  public int ladderLength(String start, String end, Set<String> dict) {
  2     // 超时了,dict很大的时候,isValidChange 用时过长。
  3     if(start == null || end == null || dict == null) return 0;
  4     if(isValidChange(start,end)) return 2;
  5     List<String> list = new ArrayList<String>();
  6     list.add(start);
  7     return searchValidChange(list, dict, end);
  8 }
  9 private int searchValidChange(List<String> list, Set<String> dict,String end) {
 10     int level = 1;
 11     int pos = 0;
 12     while(list.size() < dict.size() + 1) {
 13         int len = list.size();
 14         while(pos < len) {
 15             for(String s1 : dict) {
 16                 if(list.contains(s1)) continue;
 17                 if(isValidChange(list.get(pos), s1)) {
 18                     if(isValidChange(s1, end)) return level+2;
 19                     list.add(s1);
 20                 }
 21             }
 22             pos++;
 23         }
 24         level++;
 25     }
 26     return 0;
 27 }
 28 private boolean isValidChange(String s1, String s2) {
 29     if(s1.length() != s2.length()) return false;
 30     int count = 0;
 31     for(int i = 0; i < s1.length(); i++) {
 32     if(s1.charAt(i) == s2.charAt(i)) continue;
 33         count++;    
 34         //if(count > 1) return false;
 35     }
 36     return count == 1;
 37 }
 38 //----------------------------------------------------
 39  public int ladderLength(String start, String end, Set<String> dict) {
 40         if (dict == null) {
 41             return 0;
 42         }
 43 
 44         if (start.equals(end)) {
 45             return 1;
 46         }
 47         
 48         dict.add(start);
 49         dict.add(end);
 50 
 51         HashSet<String> hash = new HashSet<String>();
 52         Queue<String> queue = new LinkedList<String>();
 53         queue.offer(start);
 54         hash.add(start);
 55         
 56         int length = 1;
 57         while(!queue.isEmpty()) {
 58             length++;
 59             int size = queue.size();
 60             for (int i = 0; i < size; i++) {
 61                 String word = queue.poll();
 62                 for (String nextWord: getNextWords(word, dict)) {
 63                     if (hash.contains(nextWord)) {
 64                         continue;
 65                     }
 66                     if (nextWord.equals(end)) {
 67                         return length;
 68                     }
 69                     
 70                     hash.add(nextWord);
 71                     queue.offer(nextWord);
 72                 }
 73             }
 74         }
 75         return 0;
 76     }
 77 
 78     // replace character of a string at given index to a given character
 79     // return a new string
 80     private String replace(String s, int index, char c) {
 81         char[] chars = s.toCharArray();
 82         chars[index] = c;
 83         return new String(chars);
 84     }
 85     
 86     // get connections with given word.
 87     // for example, given word = 'hot', dict = {'hot', 'hit', 'hog'}
 88     // it will return ['hit', 'hog']
 89     private ArrayList<String> getNextWords(String word, Set<String> dict) {
 90         ArrayList<String> nextWords = new ArrayList<String>();
 91         for (char c = 'a'; c <= 'z'; c++) {
 92             for (int i = 0; i < word.length(); i++) {
 93                 if (c == word.charAt(i)) {
 94                     continue;
 95                 }
 96                 String nextWord = replace(word, i, c);
 97                 if (dict.contains(nextWord)) {
 98                     nextWords.add(nextWord);
 99                 }
100             }
101         }
102         return nextWords;
103     }

View Code

 

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 //懒得看了,bfs写的就问题很大。用一个队列就能解决的问题,套了半天map,死循环,还绕。
 2 private Map<String, Integer> map;
 3 private int minLen = Integer.MAX_VALUE;
 4 private List<List<String>> rsts;
 5 private Set<String> dict;
 6 public List<List<String>> findLadders(String start, String end, Set<String> dict) {
 7     // write your code here  
 8     if(start == null || end == null) return null;
 9     rsts = new ArrayList<>();
10     List<String> rst = new ArrayList<String>();
11     rst.add(start);
12     if(start.equals(end)) {
13         rsts.add(new ArrayList<String>(rst));
14         return rsts;
15     }
16     if(dict == null) return null;
17     map = findShortestLen(dict, end);
18     this.dict = dict;
19     dict.add(end);
20     //dict.add(start);
21     dfs(rst, start, end);
22     return rsts;
23 }
24 //dfs
25 private void dfs(List<String> rst,String start, String end) {
26     if(map.get(start) != null && map.get(start) == 2 && rst.size() + 1 == minLen) {
27         List<String> addRst = new ArrayList<String>(rst);
28         addRst.add(end);
29         rsts.add(addRst);
30     }
31     List<String> list = findNextWords(dict, start);
32     for(String s : list) {
33         //List<String> addList = new ArrayList<String>();
34         if(!map.containsKey(s)) continue;
35         if(minLen < rst.size() + map.get(s)) continue;
36         else {
37             minLen = rst.size() + map.get(s);    
38             rst.add(s);
39             dfs(rst, s, end );
40             rst.remove(rst.size() - 1);    
41         }
42         
43     }
44     return;
45 }
46 //bfs    
47 private Map<String, Integer> findShortestLen(Set<String> dict, String end) {
48     Map<String, Integer> map = new HashMap<>();
49     map.put(end, 1);
50     int len = 1;
51     while(map.size() < dict.size()) {  ///zzz, abc, abd,   zzz永远也放不进map,死循环,先不管。    
52         Map<String, Integer> temp = new HashMap<>();
53         for(String s1 : map.keySet()) {
54             if(map.get(s1) != len) continue;
55             List<String> list = findNextWords(dict, s1);
56             if(list == null) continue;
57             for(String s2 : list) {
58                 if(map.containsKey(s2) || temp.containsKey(s2)) continue;
59                 temp.put(s2, len + 1);
60             }
61         }
62         len++;
63         map.putAll(temp);
64     }
65     return map;
66 }
67 private List<String> findNextWords(Set<String> dict, String end) {
68     List<String> list = new ArrayList<String>();
69     for(int i = 'a'; i <= 'z'; i++) {
70         for(int j = 0; j < end.length(); j++) {
71             if(i == end.charAt(j)) continue;
72             String s = replaceOneChar(end, j, (char)i);
73             if(dict.contains(s)) list.add(s);
74         }
75     }
76     return list;
77 }
78 private String replaceOneChar(String end, int pos, char c) {
79     char[] chars = end.toCharArray();
80     chars[pos] = c;
81     return Arrays.toString(chars);
82 }

接龙2_Me_wrong

 

九章算法_九章算法(杭州)科技有限公司
九章算法_九章算法(杭州)科技有限公司

 1 public List<List<String>> findLadders(String start, String end, Set<String> dict) {
 2     List<List<String>> rsts = new ArrayList<>();
 3     List<String> rst = new ArrayList<String>();
 4     Map<String,List<String>> map = new HashMap(); 
 5     Map<String, Integer> distance = new HashMap();
 6     dict.add(start);
 7     dict.add(end); //避免dict中有无start和end造成的分类讨论
 8     bfs(map, distance, start , end, dict);
 9     dfs(rsts,map, distance,rst, end, start);
10     return rsts;
11 }
12 //从end开始添加
13 private void dfs(List<List<String>> rsts, Map<String,List<String>> map, Map<String, Integer> distance, List<String> rst, String curr,
14                  String start) {
15     rst.add(curr);
16     if(curr.equals(start)) {
17         Collections.reverse(rst);
18         rsts.add(new ArrayList(rst));
19         Collections.reverse(rst);
20         return;
21     }
22 /*    不要这样取元素
23     List<String> nexts = findNexts(dict, curr);
24     for(String next : nexts) {
25         if(distance.get(next) +1 == distance.get(curr)) {
26             dfs(rsts,map, distance, rst, next, start, dict);
27         }
28     }*/
29        /* 这样只能取出一种结果来
30         List<String> list = map.get(curr);
31         dfs(rsts,map, distance, rst, list.get(list.size() - 1) , start, dict);*/
32         List<String> list = map.get(curr);
33         for(String s : list) {
34             if(distance.get(s) +1 == distance.get(curr)) {
35                 dfs(rsts,map, distance, rst, s , start);
36             }
37         }
38     rst.remove(rst.size() - 1);
39     
40 }
41 //计算每一个字符串到start的路径距离 
42 private void bfs(Map<String,List<String>> map, Map<String, Integer> distance, String start, String end, Set<String> dict) {
43     Queue<String> q = new LinkedList();
44     q.offer(start);
45     distance.put(start, 0);
46     for(String s : dict) {
47         map.put(s, new ArrayList());
48     }
49     while(!q.isEmpty()) {
50         String curr = q.poll();
51         List<String> nexts = findNexts(dict, curr);
52         for(String next : nexts) {
53         /*    这样只能取出一种接过来
54             if(distance.containsKey(next)) continue;
55             distance.put(next, distance.get(curr) + 1);
56             map.get(next).add(curr);
57             q.offer(next);*/
58             map.get(next).add(curr);
59             if(!distance.containsKey(next)) {
60                 distance.put(next, distance.get(curr) + 1);
61                 q.offer(next);
62             }
63         }
64     }
65 }
66 private List<String> findNexts(Set<String> dict, String curr) {
67     List<String> nexts = new ArrayList();
68     for(char ch = 'a'; ch <='z'; ch++) {
69         for(int i = 0; i < curr.length(); i++) {
70             if (ch == curr.charAt(i)) continue;
71             String s = curr.substring(0, i) + ch + curr.substring(i+1);
72             if(dict.contains(s)) {
73                 nexts.add(s);
74             }
75         }    
76     }
77     return nexts;
78 }

还是wrong,不知道哪里有错

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/168352.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • assertEquals

    assertEqualsassertEqualspublicstaticvoidassertEquals(longexpected,longactual)Assertsthattwolongsare

  • oc 可变參数传递

    oc 可变參数传递

  • 微服务架构-实现技术之具体实现工具与框架5:Spring Cloud Feign与Ribbon原理与注意事项

    微服务架构-实现技术之具体实现工具与框架5:Spring Cloud Feign与Ribbon原理与注意事项目录一、SpringCloudFeign概述与工作原理解读(一)服务间调用的几种方式(二)Feign概述二、FeignClent注解剖析+SpringCloudFeign基本功能配置解读(一)@FeignClient注解剖析(二)SpringCloudFeign基本功能配置(三)Feign请求超时问题方法一方法二方法三三、SpringC…

  • wrapper 添加 jpda

    wrapper 添加 jpda

  • 红楼品鉴「建议收藏」

    红楼品鉴「建议收藏」红楼梦曹雪芹(1715-1763)案头文学,很多心理活动,心理描写很成功,特别是黛玉,因此在电视剧中黛玉的角色很难演,但是在戏曲中通过唱词比较好表达。本人强推裴效维评注的红楼梦版本,全套三本,评注很详细,有很多诗词的解释。(一)人物关系贾代善娶了金陵史家的小姐(贾母)宁国府人丁稀少,贾敬很早就到寺庙里炼丹求药,将他的爵位世袭给了贾珍。水字辈、代字辈、文字辈、…

  • java 成绩管理系统 报告_Java学生成绩管理系统实验报告

    java 成绩管理系统 报告_Java学生成绩管理系统实验报告实验名称实验类型实验编号学生成绩管理系统□验证实验学时√综合1分组号指导教师8+101实验日期实验时间实验地点6A-413一、实验目的和要求(1)掌握java的基本数据类型;掌握数组的定义和使用;(2)掌握java语言中的控制结构的使用;(3)掌握java语言中的类的定义与使用;(4)掌握java语言中继承、多态、接口、抽象类、异常处理等;…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号