4Sum : **
这题用的是比较直观点思路,调用3Sum,而3Sum 调用 2Sum
2Sum 点方法是俩边夹逼。
注意 ⚠ : for loop 去重 和 while loop 去重的用法。
是一道很好的练习细节的题目。 我现在的水平在非IDE下写代码 感觉妹五行就会有一个compile error... 淡定。。重点关注逻辑错误
public class Solution {
public List
> fourSum(int[] nums, int target) {
List
> res = new ArrayList
>(); List
> temp = new ArrayList
>(); if(nums == null || nums.length == 0) return res; Arrays.sort(nums); for(int i=0; i
0 && nums[i] == nums[i-1]) continue; int new_target = target - nums[i]; temp = threeSum(nums,new_target,i+1,nums.length-1); for(List
t : temp){ t.add(0,nums[i]); res.add(t); } } return res; } public List
> threeSum(int[] nums, int target, int l, int r){ List
> res = new ArrayList
>(); List
> temp = new ArrayList
>(); for(int i=l;i
l && nums[i] == nums[i-1]) continue; int new_target = target - nums[i]; temp = twoSum(nums,new_target,i+1,nums.length-1); for( List
t : temp){ t.add(0,nums[i]); res.add(t); } } return res; } public List
> twoSum(int[] nums, int target, int l, int r ){ int ll = l; int rr = r; List
> res = new ArrayList
>(); while(l < r){ if(l > ll && nums[l] == nums[l-1]){ l ++; continue; } if(r > rr && nums[r] == nums[r+1]){ r--; continue; } List
temp = new ArrayList
(); if(nums[l] + nums[r] == target){ temp.add(nums[l]); temp.add(nums[r]); res.add(temp); l ++; r --; }else if(nums[l] + nums[r] < target) l ++; else r --; } return res; } }
Sliding Window. Keep this standard method in mind. First augment sum before checking sum, Re-check " l > 0 " to decide whether return 0 or res.
public class Solution {
public int minSubArrayLen(int s, int[] nums) {
int sum = 0;
int res = nums.length;
int l = 0;
int r = -1;
for(int i=0; i< nums.length; i++){
sum += nums[i];
r+=1;
while(sum >= s && r>=l){
res = Math.min(res, r-l+1);
sum -= nums[l];
l+=1;
}
}
if(l == 0)
return 0;
return res;
}
}
public class Solution {
public int minSubArrayLen(int s, int[] nums) {
int l = 0;
int r = 0;
int res = nums.length;
int sum = 0;
while(r < nums.length){
sum += nums[r++];
while( sum >= s){
res = Math.min(res,r - l);
sum -= nums[l++];
}
}
if(l==0)
return 0;
return res;
}
}
"
这道题跟
Maximum Subarray
模型上和思路上都比较类似,还是用一维动态规划中的“局部最优和全局最优法”。这里的区别是维护一个局部最优不足以求得后面的全局最优,这是由于乘法的性质不像加法那样,累加结果只要是正的一定是递增,乘法中有可能现在看起来小的一个负数,后面跟另一个负数相乘就会得到最大的乘积。不过事实上也没有麻烦很多,我们只需要在维护一个局部最大的同时,在维护一个局部最小,这样如果下一个元素遇到负数时,就有可能与这个最小相乘得到当前最大的乘积和,这也是利用乘法的性质得到的。"
--- Code_Ganker
大神就是大神。
public class Solution {
public int maxProduct(int[] A) {
int global_max = A[0];
int local_min = A[0];
int local_max = A[0];
for(int i=1; i
This would be easier if not do it in place.
When do it in place, make sure not switch with itself. Actually the condition " nums[nums[i]-1] != nums[i] " will cover "nums[i] != i+1 " always.
public class Solution {
public int firstMissingPositive(int[] nums) {
if(nums == null || nums.length == 0)
return 1;
for(int i=0;i< nums.length;i++){
while(nums[i] >= 1 && nums[i]<= nums.length && nums[nums[i]-1] != nums[i] && nums[i] != i-1){
int temp = nums[nums[i] - 1];
nums[nums[i] - 1] = nums[i];
nums[i] = temp;
}
}
for(int i=0;i
Merge Intervals : ***
The way of merging after sorting took me a long while to write it right. For each new interval in intervals, there is two operations possible. 1. if not overlapping, add to res. 2. if overlapping, modify last interval in res, merge it with the new interval.
/**
* Definition for an interval.
* public class Interval {
* int start;
* int end;
* Interval() { start = 0; end = 0; }
* Interval(int s, int e) { start = s; end = e; }
* }
*/
public class Solution {
public List
insert(List
intervals, Interval newInterval) {
List
res = new ArrayList
();
if(intervals == null){
res.add(newInterval);
return res;
}
int i = 0;
while(i< intervals.size() && intervals.get(i).end < newInterval.start){
res.add(intervals.get(i));
i++;
}
if(i < intervals.size() ){
newInterval.start = Math.min(newInterval.start, intervals.get(i).start);
}
res.add(newInterval);
while(i < intervals.size() && intervals.get(i).start <= newInterval.end){
newInterval.end = Math.max(newInterval.end, intervals.get(i).end);
i ++ ;
}
while(i < intervals.size()){
res.add(intervals.get(i));
i++;
}
return res;
}
}
Insert Interval : ***
这个题目跟之前的一样,大体思路比较清晰,但是很难写对。非常依赖具体实现,不然会麻烦很多。
/**
* Definition for an interval.
* public class Interval {
* int start;
* int end;
* Interval() { start = 0; end = 0; }
* Interval(int s, int e) { start = s; end = e; }
* }
*/
public class Solution {
public List
merge(List
intervals) {
ArrayList
Aintervals = new ArrayList
(intervals);
ArrayList
res = new ArrayList
(); if(Aintervals.size()<2) return Aintervals; Comparator
Icomparator = new Comparator
(){ public int compare(Interval a, Interval b){ return a.start - b.start; } }; Collections.sort(Aintervals,Icomparator); res.add(Aintervals.get(0)); for(int i=1; i
= b.start){ a.start = Math.min(a.start,b.start); a.end = Math.max(a.end,b.end); }else{ res.add(b); } } return res; } }
一道brain fuck 的题目。 难度在 largestRectangleArea() . 理解起来都花了很久。 在leetcode上po了解释。 参考大神链接 :
Code_Ganker
public class Solution {
public int maximalRectangle(char[][] matrix) {
if(matrix == null || matrix.length == 0|| matrix[0] == null || matrix[0].length == 0)
return 0;
int[] height = new int[matrix[0].length] ;
int res = 0;
for(int i=0;i
stack = new LinkedList
();
int res = 0;
int i;
for(i=0; i
= height[i]){
int index = stack.pop();
int temp = stack.isEmpty() ? i*height[index] : ( (i - 1) - (stack.peek() + 1) +1 ) *height[index];
res = Math.max(res,temp);
}
stack.push(i);
}
while(!stack.isEmpty()){
int index = stack.pop();
int temp = stack.isEmpty() ? i * height[index] : ( i - stack.peek() -1 ) * height[index];
res = Math.max(res,temp);
}
return res;
}
}
Spiral Matrix :
****
一道感觉简单道题,却总也做不对的题目。。。 并没有真正理解这个题目点精髓。 m 和 n是不一样的, 如果 m == n, 这个题目和之前一道构建spiral matrix的题目是挺接近的。这个题目理解不到核心,盲目的做,按照边际错误修正是永远做不对的。。。
这个题的点关键突破口是,
m和n里面小的那一个,决定了螺旋的层数。进而决定了如果剩余一层,这一层是一行还是一列。
public class Solution {
public List
spiralOrder(int[][] matrix) {
List
res = new ArrayList
();
if(matrix == null || matrix.length == 0|| matrix[0] == null || matrix[0].length == 0)
return res;
int row = matrix.length;
int col = matrix[0].length;
int lvl = Math.min(row/2,col/2);
int l;
for(l=0 ; l
l; i--){
res.add(matrix[row-1-l][i]);
}
for(int i = row-1-l; i>l; i--){
res.add(matrix[i][l]);
}
}
if(Math.min(row,col) % 2 != 0){
if(row > col){
for(int i=l; i<= row-1-l; i++){
res.add(matrix[i][l]);
}
}else{
for(int i=l; i<= col-1-l; i++){
res.add(matrix[l][i]);
}
}
}
return res;
}
}
Word Search : **
一道经典道图的DFS题目。对每一个点搜全图,DFS耗时O(m*n), 所有一共耗时O(m*n * m*n)
与树的DFS不同,图是有环多,所以在一次DFS中,是要记录节点是否已经访问。这种访问信息每一支DFS是独立的。
所以对于储存访问与否的矩阵 record的维护上,需要保证不同支的DFS不相互干扰,同支的DFS保持一致。然后就是注意返回true的判断条件。
public class Solution {
public boolean exist(char[][] board, String word) {
if(word==null || word.length()==0)
return true;
if(board==null || board.length==0 || board[0] == null || board[0].length==0)
return false;
char[] str = word.toCharArray();
boolean[][] record = new boolean[board.length][board[0].length];
for(int i=0;i
= 0 && col >= 0 && row < board.length && col < board[0].length && ! record[row][col] && board[row][col] == str[index]){
record[row][col] = true;
boolean res = helper(board,str,index+1,row+1,col,record) || helper(board,str,index+1,row-1,col,record) ||helper(board,str,index+1,row,col+1,record) ||helper(board,str,index+1,row,col-1,record) ;
record[row][col] = false;
return res;
}
return false;
}
}