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

九章算法_九章算法(杭州)科技有限公司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)
blank

相关推荐

  • JavaWeb之HttpSession

    JavaWeb之HttpSessionHttpSession一、概述HttpSession是由JavaWeb提供的,用来会话跟踪的类。session是服务器端对象,保存在服务器端!!!HttpSession是Servlet三大域对象之一,所以它也有setAttribute()、getAttribute()、removeAttribute()方法。HttpSession底层依赖Cookie,或是URL重写!二、HttpSe…

  • dubbo负载均衡策略配置

    dubbo负载均衡策略配置前言在生产环境中,服务的集群部署是常有的事,从消费端来说,本身并不关注所需要的服务是由哪台机器提供,但是为了应用的健壮性和高可用性,从消费端来说,可以配置一定的负载均衡策略,确保消费端的应用能够及时获取到服务的响应数据dubbo负载均衡策略dubbo内置了四种负载均衡算法供开发中调用random随机算法,是Dubbo默认的负载均衡算法,多台机器上的服务随机选取一台的服务进行调用,如果各机器的性能相差不大的情况下,可以考虑使用这种策略。但这种策略可能存在服务堆积问题roundrobin轮询

  • Gram矩阵计算实例「建议收藏」

    Gram矩阵计算实例「建议收藏」一开始没搞明白具体咋计算,后来经人指点,记录下:matlab代码如下:’代表向量的转置x1=[3,3]’,x2=[4,3]’,x3=[1,1]’,G=[x1’*x1,x1’*x2,x1’*x3;x2’*x1,x2’*x2,x2’*x3;x3’*x1,x3’*x2,x3’*x3]得到Gram矩阵如下:G=18…

  • Pytorch 转置卷积

    Pytorch 转置卷积环境使用Kaggle里免费建立的Notebook教程使用李沐老师的动手学深度学习网站和视频讲解小技巧:当遇到函数看不懂的时候可以按查看函数详解。卷积不会增大输入的高和宽,通常要么不变,要么减半。而转置卷积则可以用来增大输入高宽。假设忽略通道,步幅为1且填充为0。输入张量形状为nh×nwn_h\timesn_wnh​×nw​,卷积核形状为kh×kwk_h\timesk_wkh​×kw​。共产生nhnwn_hn_wnh​nw​个中间结果。每个中间结果都是一个(nh+k

  • 数仓建模—数据安全「建议收藏」

    数仓建模—数据安全「建议收藏」数据安全差分隐私差分隐私是用来防范差分攻击的,差分隐私(英语:differentialprivacy)是密码学中的一种手段,旨在提供一种当从统计数据库查询时,最大化数据查询的准确性,同时最大限度减少识别其记录的机会比如有一群人出去聚餐,那么其中某人是否是单身狗就属于差分隐私。为了更形式化地描述差分隐私,我们需要先定义相邻数据集。现给定两个数据集D和D’,若它们有且仅有一条数据不一样,那我们就称此二者为相邻数据集。那么对于一个随机化算法(所谓随机化算法,是指对特定输入,该算法的输出不是固定值,而是服

  • 几种常见的距离计算公式

    几种常见的距离计算公式在学习分类、聚类、预测、推荐算法的过程中常常会遇到比较两个或多个对象的相似性,而相似性的度量可以通过计算距离来实现。我们常用的距离计算公式是欧几里得距离公式,但是有时候这种计算方式会存在一些缺陷,那么就需要另外的计算方法去加以补充,本文将介绍几种在机器学习中常用的计算距离。在做很多研究问题时常常需要估算不同样本之间的相似性度量(SimilarityMeasurement),这时通常采用的方法就…

发表回复

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

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