LeetCode算法专题一:数组(2)

“Life is good!”

35.Search Insert Position

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
You may assume no duplicates in the array.

我的基础太薄弱了!我知道要用二分法,但是不知道我写的哪里不对!

class Solution {
    public int searchInsert(int[] nums, int target) {
        int len=nums.length;
        int ans = halfDrived(nums,0,len-1,target);
        return ans;
        
        
        
    }
    private int halfDrived(int[] nums,int lo, int high,int target){
        int mid = (lo+high)/2;
        if(nums[mid] == target) return mid;       
        else if(target>nums[mid]) halfDrived(nums,mid+1,high,target);
        else halfDrived(nums,lo,mid-1,target);
        return mid;
    
    }
}

参考别人的答案:

class Solution {
   public int searchInsert(int[] nums, int target) {
        
        int low = 0;
        int high = nums.length-1;
        
        while(low <= high){
          int mid = low + (high-low)/2;
            
            if(nums[mid] == target){
                return mid;
            }else if(nums[mid] > target){
                high= mid -1;
            }else{
                low = mid+1;
            }
        }
        
        return low;
    }
}

思路:

Now lets understand why this works the way it works and why the bounds are set the way they are set. The question says if we find the element we need to return the position of the element, hence we need the condition of low <= high.
Initialize low = 0 and high as nums.length-1. while low <= high we iterate and change the bounds.
Now if middle element is smaller than the target, then the potential position where we need to insert may lie from positions mid+1 till end. So we set low as mid+1. On the other hand,if the middle element is larger than the target, then the potential position will lie from low to mid-1. In either cases it cannot be mid.
So we continue iterating, and finally when low and high cross each other, we break out of the loop. Now the question is, which one to return low or high. if we consider carefully, low represents the lower bound of the potential positions where we can insert the elements. Meaning the position must be atleast low or greater. Since low and high have already crossed each other, We cannot insert at high. We have to insert at low. Hence we return low.

53.Maximum Subarray
额,这不是动态规划的题目吗?居然也是easy级别的!!!我太水了…

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

直接放弃思考了(实际上这是我第三次碰到这个题目了,一直不会!)

Analysis of this problem:
Apparently, this is a optimization problem, which can be usually solved by DP. So when it comes to DP, the first thing for us to figure out is the format of the sub problem(or the state of each sub problem). The format of the sub problem can be helpful when we are trying to come up with the recursive relation.
At first, I think the sub problem should look like: maxSubArray(int A[], int i, int j), which means the maxSubArray for A[i: j]. In this way, our goal is to figure out what maxSubArray(A, 0, A.length - 1) is. However, if we define the format of the sub problem in this way, it’s hard to find the connection from the sub problem to the original problem(at least for me). In other words, I can’t find a way to divided the original problem into the sub problems and use the solutions of the sub problems to somehow create the solution of the original one.
So I change the format of the sub problem into something like: maxSubArray(int A[], int i), which means the maxSubArray for A[0:i ] which must has A[i] as the end element. Note that now the sub problem’s format is less flexible and less powerful than the previous one because there’s a limitation that A[i] should be contained in that sequence and we have to keep track of each solution of the sub problem to update the global optimal value. However, now the connect between the sub problem & the original one becomes clearer:
maxSubArray(A, i) =( maxSubArray(A, i - 1) > 0 ? maxSubArray(A, i - 1) : 0 ) + A[i];

public int maxSubArray(int[] A) {
        int n = A.length;
        int[] dp = new int[n];//dp[i] means the maximum subarray ending with A[i];
        dp[0] = A[0];
        int max = dp[0];
        
        for(int i = 1; i < n; i++){
            dp[i] = A[i] + (dp[i - 1] > 0 ? dp[i - 1] : 0);
            max = Math.max(max, dp[i]);
        }
        
        return max;
}

(DP是从小问题到大问题)

复制CSDN某位博主的几个解法:
一.递归解法(从大问题逐步到小问题)

class Solution {

    public int res;

    public int maxSubArray(int[] nums) {
        res = nums[0];
        rec(nums, nums.length - 1);
        return res;
    }

    public int rec(int[] nums, int index) {
        if (index == 0) {
            return nums[0];
        } else {
            int pre = rec(nums, index - 1);  //先给我求出前面的最大子序和
            int cur = pre > 0 ? pre + nums[index] : nums[index];
            res = Math.max(cur, res);
            return cur;
        }
    }
}

二.滚动优化
类似二维dp的滚动数组优化,因为每个位置只需要它前面的一个位置,所以我们只需要用一个变量保存即可。

class Solution {

    public int maxSubArray(int[] nums) {
        int preMax = nums[0];
        int max = nums[0];
        for (int i = 1; i < nums.length; i++) {
            preMax = preMax > 0 ? preMax + nums[i] : nums[i];
            max = Math.max(max, preMax);
        }
        return max;
    }
}


三.分治解法

思路:
找到中间位置,所求子串不是在中间位置的左边,就是右边,还有中间位置两边;
中间位置左边右边的和最大的子串可以递归地求得;
再求中间位置往左挨个加的最大和以及中间位置往右挨个数的最大和,这两个和就是子串跨越中间位置时的最大和;
这三个最大和中的最大值就是所求最大值;
这里要注意LMax = process(arr,L,mid),这里的右边界不是mid-1,而是mid,因为边界是L==R的时候返回arr[L],而且我们计算crossMax的时候包括了arr[mid],就不需要再加上arr[mid]。
————————————————
版权声明:本文为CSDN博主「zxzxin」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zxzxzx0119/article/details/81807083

class Solution {
    
    public int maxSubArray(int[] nums) {
        if (nums == null || nums.length == 0)
            return 0;
        return rec(nums, 0, nums.length - 1); 
    }

    //返回这个之间的最大子序和
    private int rec(int[] arr, int L, int R) {
        if (L == R)
            return arr[L];
        int mid = L + (R - L) / 2;
        int LMax = rec(arr, L, mid);
        int RMax = rec(arr, mid + 1, R);

        int sum = 0, LSumMax = Integer.MIN_VALUE, RSumMax = Integer.MIN_VALUE;

        for (int i = mid; i >= L; i--) {
            sum += arr[i];
            if (sum > LSumMax) {
                LSumMax = sum;
            }
        }
        sum = 0;
        for (int i = mid + 1; i <= R; i++) {
            sum += arr[i];
            if (sum > RSumMax) {
                RSumMax = sum;
            }
        }
        int crossMax = LSumMax + RSumMax;

        //compare crossMax、LMax,RMax
        if (LMax >= RMax && LMax >= crossMax)
            return LMax;
        if (RMax >= LMax && RMax >= crossMax)
            return RMax;
        return crossMax;
    }
}

(未理解)

如何输出这个最大子列呢?
和我想的一样,有了以上的办法,我们就可以求出最大和以及右边界.通过不断从右边减少子列的元素,直到sum为零可以判断出左边界.

66Plus One

Given a non-empty array of digits representing a non-negative integer, plus one to the integer.
The digits are stored such that the most significant digit is at the head of the list, and each element in the array contain a single digit.
You may assume the integer does not contain any leading zero, except the number 0 itself.

(额完全不知道怎么做)

看到Discussion上很优雅的一个解法:

public int[] plusOne(int[] digits) {
        
    int n = digits.length;
    for(int i=n-1; i>=0; i--) {
        if(digits[i] < 9) {
            digits[i]++;
            return digits;
        }
        
        digits[i] = 0;
    }
    
    int[] newNumber = new int [n+1];
    newNumber[0] = 1;
    
    return newNumber;
}

The last part of code is only for the case that the whole input array is 9s.
For example : 99999-----> 100000
Any other case would return in the loop.

88 Merge Sorted Array

Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.
Note:
The number of elements initialized in nums1 and nums2 are m and n respectively.
You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2.

额什么玩儿,想了这么久还是做不对
下面是我的错误代码:

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
      
        int[] Newnums = new int[m+n];
        for(int index=0;index<n+m;index++){
            int i=0,j=0;
            while(i<m&&j<n){
            if(nums1[i]>nums2[j]){
                Newnums[index] = nums2[j++];
            }
            else Newnums[index] = nums1[i++];
                
            }
           if(i==m) Newnums[index] = nums2[j++];
            else Newnums[index] = nums1[i++];
                
            
        }
        nums1 = Newnums;
        
    }
}

输出的结果和num1数组是一样的,而且我感觉自己新开一个数组也不对.
Discussion上看到一种很好的解法:

class Solution {
public:
    void merge(int A[], int m, int B[], int n) {
        int i=m-1;
		int j=n-1;
		int k = m+n-1;
		while(i >=0 && j>=0)
		{
			if(A[i] > B[j])
				A[k--] = A[i--];
			else
				A[k--] = B[j--];
		}
		while(j>=0)
			A[k--] = B[j--];
    }
};

最后一个语句值得思考,很妙!我重写了一遍是while(j>0),结果有错!因为j现在表示的是数组下标,可以为0的.

118Pascal’s Triangle

Given a non-negative integer numRows, generate the first numRows of Pascal’s triangle.

杨辉三角的几个特性:
1.每一行首尾皆为1
2.a[i][j[=a[i-1][j-1]+a[i-1][j]

下面是一个不太懂的解法:

public class Solution {
public List<List<Integer>> generate(int numRows)
{
	List<List<Integer>> allrows = new ArrayList<List<Integer>>();
	ArrayList<Integer> row = new ArrayList<Integer>();
	for(int i=0;i<numRows;i++)
	{
		row.add(0, 1);
		for(int j=1;j<row.size()-1;j++)
			row.set(j, row.get(j)+row.get(j+1));
		allrows.add(new ArrayList<Integer>(row));
	}
	return allrows;
	
}
}

一个我可以理解的解法:

class Solution{
	public List<List<Integer>> generate(int numRows){
		List<List<Integer>> result = new ArrayList<>();
		for(int i=0;i<numRows;i++){
			List<Integer> list = new ArrayList<>();

			for(int j=0;j<i+1;j++){
				if(j==0||j==i){
					list.add(1);
				}
				else{
					int a=result.get(i-1).(j-1);
					int b=result.get(i-1).(j);
					list.add(a+b);
				}
				}
				return result;
			}
		}	
  1. Pascal’s Triangle II

Given a non-negative index k where k ≤ 33, return the kth index row of the Pascal’s triangle.
Note that the row index starts from 0.

也是不会!!!还是不会!!!

public static List<Integer> getRow2(int rowIndex) {
	List<Integer> ret = new ArrayList<Integer>();
	ret.add(1);
	for (int i = 1; i <= rowIndex; i++) {
		for (int j = i - 1; j >= 1; j--) {
			int tmp = ret.get(j - 1) + ret.get(j);
			ret.set(j, tmp);
		}
		ret.add(1);
	}
	return ret;

“加油加油加油!!!”

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值