提交 4ca0257b 编写于 作者: L liu13

20190715

上级 abfdac66
...@@ -23,7 +23,7 @@ public class lc102 { ...@@ -23,7 +23,7 @@ public class lc102 {
if(root==null) if(root==null)
return res; return res;
qu.add(root); qu.add(root);
while(!qu.isEmpty()){ while(!qu.isEmpty()){ //两个while
int size = qu.size(); int size = qu.size();
List<Integer> temp = new ArrayList<>(); List<Integer> temp = new ArrayList<>();
while(size>0){ while(size>0){
......
...@@ -20,20 +20,20 @@ public class lc113 { ...@@ -20,20 +20,20 @@ public class lc113 {
} }
} }
public List<List<Integer>> pathSum(TreeNode root, int sum) { public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> res = new ArrayList<>(); List<List<Integer>> res = new ArrayList();
helper(res, root, sum, 0, new ArrayList<>()); helper(res, new ArrayList(), root, sum);
return res; return res;
} }
public void helper(List<List<Integer>> res, TreeNode root, int sum, int curr, List<Integer> curr_ls) { public void helper(List<List<Integer>> res, List<Integer> cur, TreeNode root, int sum){
if(root==null) return; if(root==null) return;
curr_ls.add(root.val); cur.add(root.val);
if(curr+root.val==sum && root.left==null && root.right==null) { //到叶子节点 if(root.left==null&&root.right==null&&root.val==sum){ //到叶子节点
res.add(new ArrayList<>(curr_ls)); res.add(new ArrayList(cur));
curr_ls.remove(curr_ls.size()-1); }else{
return; helper(res, cur, root.left, sum-root.val);
helper(res, cur, root.right, sum-root.val);
} }
helper(res, root.left, sum, curr+root.val, curr_ls); cur.remove(cur.size()-1);
helper(res, root.right, sum, curr+root.val, curr_ls); return;
curr_ls.remove(curr_ls.size()-1);
} }
} }
package code; package code;
/* /*
* 122. Best Time to Buy and Sell Stock III * 123. Best Time to Buy and Sell Stock III
* 题意:买卖股票最大利润,只能买卖2次 * 题意:买卖股票最大利润,只能买卖2次
* 难度:Hard * 难度:Hard
* 分类:Array, Dynamic Programming * 分类:Array, Dynamic Programming
......
...@@ -10,6 +10,7 @@ import java.util.List; ...@@ -10,6 +10,7 @@ import java.util.List;
* 思路:典型回溯法,注意向res添加内容时要重新new一下 * 思路:典型回溯法,注意向res添加内容时要重新new一下
* Tips: lc5, lc9, lc125, lc131, lc234, lc647 * Tips: lc5, lc9, lc125, lc131, lc234, lc647
* lc39 * lc39
* lc132
* 判断是否为回文的方法: * 判断是否为回文的方法:
* 1. 从中心往两边扩充,中心可能是一个字符,也可能是两个字符 * 1. 从中心往两边扩充,中心可能是一个字符,也可能是两个字符
* 2. dp,利用之前计算的结果,只判断边缘两个字符是否相等,从后往前dp * 2. dp,利用之前计算的结果,只判断边缘两个字符是否相等,从后往前dp
......
package code;
import java.util.Arrays;
/*
* 132. Palindrome Partitioning II
* 题意:最少切几刀,回文串
* 难度:Hard
* 分类:Dynamic Programming
* 思路:和lc300思路很像,只是多了判断。dp[i]表示从0到i这一段切法的最小值,每次遍历前边的结果,看能否接上。
* 可以把判断回文和dp两个合并,因为用dp的形式判断回文
* Tips:lc300
* bingo!
*/
public class lc132 {
public int minCut(String s) {
int[] dp = new int[s.length()+1];
Arrays.fill(dp, s.length()); //fill最大值
dp[0] = 0;
for(int i=1; i<dp.length; i++){
for(int j=0; j<=i; j++){ //注意<=
if(dp[j]!=s.length() && isPalindrome(s.substring(j,i)))
dp[i] = Math.min(dp[i], dp[j]+1);
}
}
return dp[s.length()]-1; //要-1 最后一刀是在末尾
}
public Boolean isPalindrome(String str){
if(new StringBuilder(str).reverse().toString().equals(str)) return true; //reverse一下
else return false;
}
public int minCut2(String s) {
char[] c = s.toCharArray();
int n = c.length;
int[] cut = new int[n];
boolean[][] pal = new boolean[n][n];
for(int i = 0; i < n; i++) {
int min = i;
for(int j = 0; j <= i; j++) {
if(c[j] == c[i] && (j + 1 > i - 1 || pal[j + 1][i - 1])) {
pal[j][i] = true;
min = j == 0 ? 0 : Math.min(min, cut[j - 1] + 1);
}
}
cut[i] = min;
}
return cut[n - 1];
}
}
...@@ -6,8 +6,10 @@ package code; ...@@ -6,8 +6,10 @@ package code;
* 分类:Dynamic Programming * 分类:Dynamic Programming
* 思路:动态规划 * 思路:动态规划
* Tips:巧妙的方法,防止了复杂的操作,通过遍历之前计算出来的结果 * Tips:巧妙的方法,防止了复杂的操作,通过遍历之前计算出来的结果
* 递归的方法本质和dp是一样的,记住用备忘录算法,把之前的结果记下来
* lc140 * lc140
*/ */
import java.util.HashMap;
import java.util.List; import java.util.List;
public class lc139 { public class lc139 {
...@@ -22,4 +24,16 @@ public class lc139 { ...@@ -22,4 +24,16 @@ public class lc139 {
} }
return dp[s.length()]; return dp[s.length()];
} }
HashMap<String, Boolean> hm = new HashMap();
public boolean wordBreak2(String s, List<String> wordDict) {
if(hm.containsKey(s)) return hm.get(s);
if(s.length() == 0) return true;
Boolean flag = false;
for(String word:wordDict){
if(s.startsWith(word)) flag = flag||wordBreak(s.substring(word.length()), wordDict); //注意函数 startsWith
}
hm.put(s, flag);
return flag;
}
} }
...@@ -14,15 +14,13 @@ public class lc141 { ...@@ -14,15 +14,13 @@ public class lc141 {
ListNode(int x) { val = x; } ListNode(int x) { val = x; }
} }
public boolean hasCycle(ListNode head) { public boolean hasCycle(ListNode head) {
if(head==null) if(head==null||head.next==null) return false;
return false;
ListNode faster = head;
ListNode slow = head; ListNode slow = head;
while( faster.next!=null && faster.next.next!=null){ //注意判断条件,slow一定不等于null,不用判断了 ListNode fast = head.next;
while(fast!=null&&fast.next!=null){ //注意判断条件,slow一定不等于null,不用判断了
slow = slow.next; slow = slow.next;
faster = faster.next.next; fast = fast.next.next;
if(slow==faster) if(fast==slow) return true;
return true;
} }
return false; return false;
} }
......
...@@ -32,4 +32,23 @@ public class lc142 { ...@@ -32,4 +32,23 @@ public class lc142 {
} }
return null; return null;
} }
public ListNode detectCycle2(ListNode head) {
if(head==null||head.next==null) return null;
ListNode slow = head;
ListNode fast = head.next;
while(fast!=null&&fast.next!=null){
slow = slow.next;
fast = fast.next.next;
if(slow==fast){
slow = slow.next;
while(head!=slow){
head = head.next;
slow = slow.next;
}
return slow;
}
}
return null;
}
} }
...@@ -25,7 +25,7 @@ public class lc148 { ...@@ -25,7 +25,7 @@ public class lc148 {
if( head==null || head.next == null ){ if( head==null || head.next == null ){
return head; return head;
} }
ListNode slow = head; ListNode slow = head; //记一下
ListNode fast = head.next; ListNode fast = head.next;
while( fast!=null && fast.next!=null ){ //把链表分成两半 while( fast!=null && fast.next!=null ){ //把链表分成两半
slow = slow.next; slow = slow.next;
......
...@@ -23,7 +23,7 @@ public class lc207 { ...@@ -23,7 +23,7 @@ public class lc207 {
for (int i = 0; i < prerequisites.length ; i++) { for (int i = 0; i < prerequisites.length ; i++) {
int node1 = prerequisites[i][0]; int node1 = prerequisites[i][0];
int node2 = prerequisites[i][1]; int node2 = prerequisites[i][1];
graph[node2][node1] = 1; graph[node2][node1] = 1; //存下邻接矩阵,方便后续查找是否有边
indegree[node1]++; //存下入度,入度为0时,表示该课程可以修 indegree[node1]++; //存下入度,入度为0时,表示该课程可以修
} }
Stack<Integer> st = new Stack(); Stack<Integer> st = new Stack();
......
...@@ -19,8 +19,7 @@ public class lc226 { ...@@ -19,8 +19,7 @@ public class lc226 {
} }
public TreeNode invertTree(TreeNode root) { public TreeNode invertTree(TreeNode root) {
//递归 //递归
if(root==null) if(root==null) return null;
return null;
TreeNode temp = root.left; TreeNode temp = root.left;
root.left = root.right; root.left = root.right;
root.right = temp; root.right = temp;
......
...@@ -6,6 +6,7 @@ package code; ...@@ -6,6 +6,7 @@ package code;
* 分类:Binary Search, Dynamic Programming * 分类:Binary Search, Dynamic Programming
* 思路:基本的思路是dp[i]记录以nums[i]结尾的最长长度,每次遍历 dp[i] 得到dp[i+1],复杂度为O(n^2)。最优的解法是O(nlgn),dp[i]是递增的数组,每次插入时二分查找是lgn。 * 思路:基本的思路是dp[i]记录以nums[i]结尾的最长长度,每次遍历 dp[i] 得到dp[i+1],复杂度为O(n^2)。最优的解法是O(nlgn),dp[i]是递增的数组,每次插入时二分查找是lgn。
* Tips:经典题目,记一下 * Tips:经典题目,记一下
* lc132
*/ */
import java.util.Arrays; import java.util.Arrays;
......
...@@ -27,4 +27,18 @@ public class lc309 { ...@@ -27,4 +27,18 @@ public class lc309 {
} }
return Math.max(s,b); return Math.max(s,b);
} }
public int maxProfit2(int[] prices) {
if(prices.length==0) return 0;
int[] sell = new int[prices.length];
int[] buy = new int[prices.length];
sell[0] = 0;
buy[0] = -prices[0];
for(int i=1; i<prices.length; i++){
sell[i] = Math.max(sell[i-1], buy[i-1]+prices[i]);
if(i==1) buy[i] = Math.max(buy[i-1], 0-prices[i]);
else buy[i] = Math.max(buy[i-1], sell[i-2]-prices[i]);
}
return Math.max(sell[prices.length-1],buy[prices.length-1]);
}
} }
...@@ -4,12 +4,12 @@ package code; ...@@ -4,12 +4,12 @@ package code;
* 题意:找出排列组合的下一个排列 * 题意:找出排列组合的下一个排列
* 难度:Medium * 难度:Medium
* 分类:Array * 分类:Array
* 思路:从后往前找第一个变小的数x,从这个数之后的数中找出第一个比x大的数,交换,再把之后的数逆序即可 * 思路:从后往前找第一个变小的数x,从后往前找出比第一个x大的数,交换,再把之后的数逆序即可
* Tips:很典型的排列组合题,思路方法记忆一下。注意比较时是否有=。 * Tips:很典型的排列组合题,思路方法记忆一下。注意比较时是否有=。
*/ */
public class lc31 { public class lc31 {
public static void main(String[] args) { public static void main(String[] args) {
int[] nums = {2,3,1,3,3}; int[] nums = {1,2,3};
nextPermutation(nums); nextPermutation(nums);
for (int i:nums){ for (int i:nums){
System.out.println(i); System.out.println(i);
...@@ -19,27 +19,25 @@ public class lc31 { ...@@ -19,27 +19,25 @@ public class lc31 {
public static void nextPermutation(int[] nums) { public static void nextPermutation(int[] nums) {
int ptr = nums.length-1; int ptr = nums.length-1;
//从后往前找第一个变小的数x //从后往前找第一个变小的数x 从后往前找出比第一个x大的数
while(ptr>0&&nums[ptr-1]>=nums[ptr]){// 注意是 >= {5,1,1} , 等于-- while(ptr>0&&nums[ptr-1]>=nums[ptr]){// 注意是 >= {5,1,1} , 等于--
ptr--; ptr--;
} }
ptr--;
if(ptr!=0){ if(ptr!=-1){
//从这个数之后的数中找出第一个比x大的数 //从后往前,找比
int n = nums[ptr]; int val = nums[ptr];
int ptr2 = ptr; int ptr2 = nums.length-1;
for(int i=ptr+1; i<nums.length; i++){ //这不用这么麻烦,后边的数有序的,这可以简化 while(ptr2>ptr){
if( nums[i]>nums[ptr-1] && nums[i]<=n ) {//注意 <= {2,3,1,3,3} if(nums[ptr2]>nums[ptr]) break;
n = nums[i]; ptr2--;
ptr2 = i;
}
} }
nums[ptr2] = nums[ptr-1]; nums[ptr] = nums[ptr2];
nums[ptr-1] = n; nums[ptr2] = val;
} }
//把之后的数逆序 //把之后的数逆序
ReverseNums(nums,ptr,nums.length-1); ReverseNums(nums,ptr+1,nums.length-1); //+1,不包含ptr那个位置
} }
public static void ReverseNums(int[] nums, int start, int end){ public static void ReverseNums(int[] nums, int start, int end){
int l = end+start; int l = end+start;
......
...@@ -28,7 +28,7 @@ public class lc32 { ...@@ -28,7 +28,7 @@ public class lc32 {
else{ else{
if(s.charAt(i-2)=='('){ // 这种情况:(())() if(s.charAt(i-2)=='('){ // 这种情况:(())()
dp[i] = dp[i-2]+2; dp[i] = dp[i-2]+2;
}else if(i-2-dp[i-1]>=0 && s.charAt(i-2-dp[i-1])=='('){ // 这种情况:()(()) }else if(i-2-dp[i-1]>=0 && s.charAt(i-2-dp[i-1])=='('){ // 这种情况:()(()) , 第一个判断是判断索引是否合法
dp[i] = dp[i-1] + dp[i-2-dp[i-1]]+2; dp[i] = dp[i-1] + dp[i-2-dp[i-1]]+2;
} }
} }
...@@ -49,7 +49,7 @@ public class lc32 { ...@@ -49,7 +49,7 @@ public class lc32 {
st.push(i); st.push(i);
else if(ch==')'){ else if(ch==')'){
st.pop(); st.pop();
if(st.isEmpty()) if(st.isEmpty()) //截断一下
st.push(i); st.push(i);
res = Math.max(res,i-st.peek()); res = Math.max(res,i-st.peek());
} }
......
...@@ -69,5 +69,21 @@ public class lc416 { ...@@ -69,5 +69,21 @@ public class lc416 {
return dp[volumn]; return dp[volumn];
} }
public boolean canPartition3(int[] nums) {
int sum = 0;
for(int i: nums) sum+=i;
if(sum%2==1) return false;
sum = sum/2;
boolean[][] dp = new boolean[nums.length+1][sum+1];
for(int i =0; i<=nums.length; i++) dp[i][0]=true; //注意赋值0
for(int i=1; i<=nums.length; i++){
for(int j=1; j<=sum; j++){
dp[i][j] = dp[i-1][j];
if(j>=nums[i-1]) dp[i][j]= dp[i][j] || dp[i-1][j-nums[i-1]]; //注意判断index是否合法
}
}
return dp[nums.length][sum];
}
} }
...@@ -17,7 +17,7 @@ public class lc76 { ...@@ -17,7 +17,7 @@ public class lc76 {
} }
public static String minWindow(String s, String t) { public static String minWindow(String s, String t) {
HashMap<Character,Integer> mp = new HashMap(); HashMap<Character,Integer> mp = new HashMap();
for (int i = 0; i < t.length() ; i++) { //统计每个字符出现的个数 for (int i = 0; i < t.length() ; i++) { // 统计每个字符出现的个数
char ch = t.charAt(i); char ch = t.charAt(i);
if(mp.containsKey(ch)) if(mp.containsKey(ch))
mp.put(ch,mp.get(ch)+1); mp.put(ch,mp.get(ch)+1);
...@@ -37,7 +37,7 @@ public class lc76 { ...@@ -37,7 +37,7 @@ public class lc76 {
if(mp.get(ch_r)>=0) // <0说明重复了 if(mp.get(ch_r)>=0) // <0说明重复了
count++; count++;
} }
while(count==t.length()){//右移左指针 while(count==t.length()){//右移左指针,注意这个判定条件
if(right-left+1<res_len){ //更新结果 if(right-left+1<res_len){ //更新结果
res_left = left; res_left = left;
res_len = right-left+1; res_len = right-left+1;
...@@ -56,4 +56,39 @@ public class lc76 { ...@@ -56,4 +56,39 @@ public class lc76 {
return ""; return "";
return s.substring(res_left,res_left+res_len); return s.substring(res_left,res_left+res_len);
} }
public String minWindow2(String s, String t) {
HashMap<Character, Integer> hm = new HashMap();
char[] t_arr = t.toCharArray();
for(int i=0; i<t_arr.length; i++){
hm.put(t_arr[i], hm.getOrDefault(t_arr[i], 0)+1);
}
int left = 0;
int right = 0;
int count = t.length();
char[] s_arr = s.toCharArray();
int res = Integer.MAX_VALUE;
int res_left = 0;
int res_right = 0;
while(right<s.length()){ //一共两个while
if(hm.containsKey(s_arr[right])){
hm.put(s_arr[right], hm.get(s_arr[right])-1);
if(hm.get(s_arr[right])>=0) count--; //别忘了这一层的判断
}
right++; //在if外边
while(count==0){ //注意判断条件
if(right-left+1<res){ //记录结果
res = right-left+1;
res_left = left;
res_right = right;
}
if(hm.containsKey(s_arr[left])){
hm.put(s_arr[left], hm.get(s_arr[left])+1);
if(hm.get(s_arr[left])>0) count++;
}
left++;
}
}
return s.substring(res_left, res_right);
}
} }
...@@ -5,7 +5,7 @@ package code; ...@@ -5,7 +5,7 @@ package code;
* 难度:Medium * 难度:Medium
* 分类:HashTable, Stack, Tree * 分类:HashTable, Stack, Tree
* 思路:左节点依次入栈二叉树中序遍历 * 思路:左节点依次入栈二叉树中序遍历
* Tips:和lc144前序,lc145后序一起看 * Tips:和lc144前序,lc145后序一起看, lc102层次遍历
*/ */
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
......
...@@ -28,7 +28,7 @@ public class lc978 { ...@@ -28,7 +28,7 @@ public class lc978 {
public int maxTurbulenceSize2(int[] A) { public int maxTurbulenceSize2(int[] A) {
int[] arr = new int[A.length-1]; int[] arr = new int[A.length-1];
for(int i=1; i<A.length; i++){ for(int i=1; i<A.length; i++){ //转换成0,1数组
if(A[i]==A[i-1]) arr[i-1] = 0; if(A[i]==A[i-1]) arr[i-1] = 0;
else if(A[i]>A[i-1]) arr[i-1] = 1; else if(A[i]>A[i-1]) arr[i-1] = 1;
else arr[i-1] = -1; else arr[i-1] = -1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册