Leetcode - Array -Easy (26,27,53,88,118,121,167,169,217,219,228,268,283)

  1. Remove Duplicates from Sorted Array
    Given a sorted array nums, remove the duplicates in-place such that each element appears only once and returns the new length.
    Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
    Example 2:
    Input: nums = [0,0,1,1,1,2,2,3,3,4]
    Output: 5, nums = [0,1,2,3,4]
    Explanation: Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively. It doesn’t matter what values are set beyond the returned length.
    这题不是真正的删除有序数组中的重复元素,只是把前面不重复的个数返回,用户根据不重复数组长度自行使用。
class Solution {
    public int removeDuplicates(int[] nums) {
        int len =nums.length;
        int slow = 0;
        if(len<=1){return len;}
        for(int j=1;j<len;j++){
            if(nums[j]!=nums[slow]){
                slow++;
                nums[slow]=nums[j];
            }
        }
        return slow+1;
    }
}
  1. Remove Element
    Given an array nums and a value val, remove all instances of that value in-place and return the new length.
    Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
    Example 1:
    Input: nums = [3,2,2,3], val = 3
    Output: 2, nums = [2,2]
    Explanation: Your function should return length = 2, with the first two elements of nums being 2.
    It doesn’t matter what you leave beyond the returned length. For example if you return 2 with nums = [2,2,3,3] or nums = [2,2,0,0], your answer will be accepted.
    类似上一题,就是用i来记录满足条件的元素。
class Solution {
    public int removeElement(int[] nums, int val) {
        int i=0;
        for(int j=0;j<nums.length;j++){
            if(nums[j]!=val){
                nums[i]=nums[j];
                i++;
            }
        }
        return i;
   }
}
  1. Search Insert Position
    Given a sorted array of distinct integers 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.
Example 1:
Input: nums = [1,3,5,6], target = 5
Output: 2
Example 4:
Input: nums = [1,3,5,6], target = 0
Output: 0

这题总结了三种比较有代表性的写法
直白的方法,遍历数组找到相等或者大的index。注意两个特殊情况——返回0和数组长度。

class Solution1 {
    public int searchInsert(int[] nums, int target) {
        if(nums.length==0){return 0;}
        for(int i=0;i<nums.length;i++){
           if(nums[i]==target || nums[i]>target){
               return i;
           }
        }
        return nums.length;
    }
}

二分法

class Solution2 {
    public int searchInsert(int[] nums, int target) {
        int low=0;
        int high=nums.length;
        while(low<high){
            int mid=low+((high-low)>>1); //可以避免溢出求中点写法,位运算更快
            if(nums[mid]>=target){
                high=mid;
            }else if(target>nums[mid]){
                low=low+1; //如果赋值mid会过不了,这个不懂
            }
        }
        return low;
    }
}

二分递归,写法更好理解

class Solution3 {
    public int searchInsert(int[] nums, int target) {
       return searchInsertHelper(nums,0,nums.length-1,target);
    }
    private int searchInsertHelper(int[] nums,int start,int end,int target){
        if(start>end){return start;}
        int mid=start+(end-start)/2;
        if(target==nums[mid]){return mid;}
        else if(target>nums[mid]){return searchInsertHelper(nums,mid+1,end,target);}
        else{return searchInsertHelper(nums,start,mid-1,target);}
    }
}
  1. Maximum Subarray
    Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Example 1:
Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Example 5:
Input: nums = [-100000]
Output: -100000

感谢网友提供—动态规划思路详解

/*动态规划的思路主要就是——遍历到当前元素之前的和<0会被舍弃,从当前元素开始从新记录和;
*如果之前和>0则将当前元素计入。然后用sum元素记录到目前位置最大的和。
*一般用dp[]数组记录和,但本方法里直接用nums记录了,所以空间上节俭了Θ(N),此方法时间复杂度为Θ(N)
*/
class Solution1 {
    public int maxSubArray(int[] nums) {
       int sum = nums[0];
        for(int i=1;i<nums.length;i++){
            if(nums[i-1]>0){
                nums[i]=nums[i-1]+nums[i];
            }
            sum = Math.max(sum,nums[i]);
        }
        return sum;
    }
}

分治法详细思路

/*
 * 此方法时间复杂度为Θ(NlogN)
*/
class Solution {
    public int maxSubArray(int[] nums) {
       return maxSubArrayDivideWithBorder(nums,0,nums.length-1);
    }
    
    private int maxSubArrayDivideWithBorder(int[] nums, int start, int end){
        if(start==end){
            return nums[start];
        } // 只有一个元素,也就是递归的结束情况
        
        int mid = start+((end-start)>>1); // 计算中间值
        int leftMax = maxSubArrayDivideWithBorder(nums,start,mid); // 计算左侧子序列最大值
        int rightMax = maxSubArrayDivideWithBorder(nums,mid+1,end); // 计算右侧子序列最大值
        // 计算包含左侧子序列最后一个元素的子序列最大值
        int leftCrossMax = Integer.MIN_VALUE;
        int leftCrossSum = 0;
        for(int i=mid;i>=start;i--){
            leftCrossSum += nums[i];
            leftCrossMax = Math.max(leftCrossSum, leftCrossMax);
        }
        // 计算包含右侧子序列最后一个元素的子序列最大值
        int rightCrossMax = Integer.MIN_VALUE;
        int rightCrossSum = 0;
        for(int i=mid+1;i<=end;i++){
            rightCrossSum += nums[i];
            rightCrossMax = Math.max(rightCrossSum, rightCrossMax);
        }
        // 计算跨中心的子序列的最大值
        int crossMax = leftCrossMax + rightCrossMax;
        // 比较三者,返回最大值
        return Math.max(crossMax, Math.max(leftMax, rightMax));
    }
}
  1. Merge Sorted Array
    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.
    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 equal to m + n) to hold additional elements from nums2.
Example 1:
Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]
class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        System.arraycopy(nums2,0,nums1,m,n);
        Arrays.sort(nums1);
    }
}
  1. Pascal’s Triangle
    Given a non-negative integer numRows, generate the first numRows of Pascal’s triangle.
Example:
Input: 5
Output:
[
     [1],
    [1,1],
   [1,2,1],
  [1,3,3,1],
 [1,4,6,4,1]
]

class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> triangle = new ArrayList<List<Integer>>();
        if(numRows==0){return triangle;}
        List<Integer> firstRow = new ArrayList<>();
        firstRow.add(1);
        triangle.add(firstRow);
        
        for(int i=1;i<numRows;i++){
            List<Integer> nRow = new ArrayList<>();
            List<Integer> prevRow = triangle.get(i-1);
            nRow.add(1);
            for(int j=1;j<i;j++){
                nRow.add(prevRow.get(j-1)+prevRow.get(j));
            }
            nRow.add(1);
            triangle.add(nRow);      
        }
        
        return triangle;
    }
}
  1. Pascal’s Triangle II
    Given an integer rowIndex, return the rowIndexth row of the Pascal’s triangle.
    Notice that the row index starts from 0.
Example 1:
Input: rowIndex = 3
Output: [1,3,3,1]
class Solution {
    public List<Integer> getRow(int rowIndex) {
        List<Integer> row = new ArrayList<Integer>();
        List<Integer> prevRow = new ArrayList<Integer>();
        row.add(1);
        prevRow.add(1);
        
        for(int i=1;i<=rowIndex;i++){
            row = new ArrayList<Integer>();
            row.add(1);
            for(int j=1;j<i;j++){
                row.add(prevRow.get(j-1)+prevRow.get(j));
            }
            row.add(1);
            prevRow = row;
        }
        
        return row;
    }
}
  1. Best Time to Buy and Sell Stock
    You are given an array prices for which prices[i] is the price of a given stock on the ith day.
    You are only permitted to complete at most one transaction. In other words, you can buy one and sell one share of the stock. You cannot sell a stock before you buy one.
    Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0.
Example 1:
Input: prices = [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
The answer is not 7-1 = 6, as selling price needs to be larger than buying price.
Example 2:
Input: prices = [7,6,4,3,1]
Output: 0
Explanation: In this case, no transactions are done and the max profit = 0.

分析:本题只能买卖一次。 动态规划法。从前向后遍历数组,记录当前出现过的最低价格,作为买入价格,并计算以当天价格出售的收益,作为可能的最大收益,整个遍历过程中,出现过的最大收益就是所求。

代码: 时间O(n),空间O(1)

class Solution {
    public int maxProfit(int[] prices) {
        int maxProfit = 0;
        int lowPrice = prices[0];
        for(int i=1;i<prices.length;i++){
            if(prices[i]<lowPrice){
                lowPrice=prices[i];
            }
            maxProfit = Math.max(maxProfit, prices[i]-lowPrice);
        }
        return maxProfit;
    }
}
  1. Best Time to Buy and Sell Stock II
    Say you have an array prices for which the ith element is the price of a given stock on day i.
    Design an algorithm to find the maximum profit. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times).
    Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).
Example 1:
Input: [7,1,5,3,6,4]
Output: 7
Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
 Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.

分析: 本题可以买卖多次。贪心法。从前向后遍历数组,只要当天的价格高于前一天的价格,就算入收益。

代码: 时间O(n),空间O(1)。

class Solution {
    public int maxProfit(int[] prices) {
        int max = 0;
        for(int i=1;i<prices.length;i++){
            if(prices[i]>prices[i-1]){
                max += prices[i]-prices[i-1];
            }
        }
        return max;
    }
}
  1. Two Sum II - Input array is sorted
    Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.
    The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.
    Note:
    Your returned answers (both index1 and index2) are not zero-based.
    You may assume that each input would have exactly one solution and you may not use the same element twice.
Example 1:
Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.

仍可以用1.Two Sum 中的方法,用HashMap记录遍历的元素和index,然后通过target-nums[i]查询。下面方法则是利用条件1)数组已排序2)没有重复使用元素,用左右两指针从排序数组两头开始比较,找到和为target的情况。

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int l = 0;
        int r = numbers.length-1;
        while(l<r){
            if(numbers[l]+numbers[r]==target){
                return new int[]{l+1,r+1};
            }else if(numbers[l]+numbers[r]>target){
                r--;
            }else{
                l++;
            }
        }
        return new int[]{0,0};
    }
}
  1. Majority Element
    Given an array nums of size n, return the majority element.
    The majority element is the element that appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array.
Example 1:
Input: nums = [3,2,3]
Output: 3

第一个想到的就是用HashMap啦,comment掉的是没有【more than n/2】这一附加条件时用变量记录的常规做法。本题中提到返回值符合大于【more than n/2】所以就钻了小空子,当遍历到符合条件的值就直接返回。

//9 ms	44.4 MB
class Solution1 {
    public int majorityElement(int[] nums) {
        HashMap<Integer,Integer> hm = new HashMap<>();
        int majority = Integer.MIN_VALUE;
        //int count = 0;
        for(int i=0;i<nums.length;i++){
            hm.put(nums[i],hm.getOrDefault(nums[i],0)+1);
            if(hm.get(nums[i])>nums.length/2){
                return nums[i];
            }
            // if(hm.get(nums[i])>count){
            //     count=hm.get(nums[i]);
            //     majority=nums[i];
            // }
        }
        return majority;
    }
}

第二个是排序法,也是利用了【more than n/2】必然是majority的条件。
偶数个元素的例子:[1122], return nums[2]
奇数个元素的例子:[112], return nums[1]

//1 ms	42.1 MB
class Solution2 {
    public int majorityElement(int[] nums) {
        Arrays.sort(nums);
        return nums[nums.length/2];
    }
}

传说中的Boyer-Moore Voting Algorithm

class Solution3 {
    public int majorityElement(int[] nums) {
        int count=0;
        int candidate = Integer.MAX_VALUE;
        for(int i=0;i<nums.length;i++){
            if(count==0){
                candidate=nums[i];
            }
            count += candidate==nums[i] ? 1 : -1;
        }
        return candidate;
    }
}
  1. Contains Duplicate
    Given an array of integers, find if the array contains any duplicates.
    Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.
    Example 1:
    Input: [1,2,3,1]
    Output: true
    下面收录的方法是时间空间复杂度均为Θ(N)的Set大法。参考答案说现实中排序法反而比较好。
    解释如下:
    For certain test cases with not very large n, the runtime of this method can be slower than Approach #2. The reason is hash table has some overhead in maintaining its property. One should keep in mind that real world performance can be different from what the Big-O notation says. The Big-O notation only tells us that for sufficiently large input, one will be faster than the other. Therefore, when n is not sufficiently large, an O(n) algorithm can be slower than an O(n log n)algorithm.
class Solution {
    public boolean containsDuplicate(int[] nums) {
	    Set<Integer> set = new HashSet<>(nums.length);
	    for (int x: nums) {
	        if (set.contains(x)) return true;
	        set.add(x);
	    }
	    return false;
   }
}

Time complexity : O(n log n)O(nlogn). Sorting is O(n log n)O(nlogn) and the sweeping is O(n)O(n). The entire algorithm is dominated by the sorting step, which is O(n log n)O(nlogn).
Space complexity : O(1)O(1). Space depends on the sorting implementation which, usually, costs O(1)O(1) auxiliary space if heapsort is used.

public boolean containsDuplicate(int[] nums) {
    Arrays.sort(nums);
    for (int i = 0; i < nums.length - 1; ++i) {
        if (nums[i] == nums[i + 1]) return true;
    }
    return false;
}
  1. Contains Duplicate II
    Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k.
Example 1:
Input: nums = [1,2,3,1], k = 3
Output: true
Example 2:
Input: nums = [1,0,1,1], k = 1
Output: true
Example 3:
Input: nums = [1,2,3,1,2,3], k = 2
Output: false

神奇的O(N)思路:利用set可以做到类似滑动窗口一样的效果,首先保证set长度不超过k, 在遍历过程中如果有新元素加入失败【set.add() 返回false】,即说明有重复元素。遍历完都没返true的说明没满足条件的重复元素。

class Solution1 {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        Set<Integer> set = new HashSet<>();
        for(int i=0;i<nums.length;i++){
            if(i>k){
                set.remove(nums[i-k-1]);
            }
            if(!set.add(nums[i])){return true;}
        }
        return false;
    }
}

另一个用Map记录的O(N)思路:map记录遍历的元素和index,如果遇到一个存在的元素,则比较两者index差值是不是小于k,如果是返回true,遍历完都没就返回false。当然每一轮要更新map。

class Solution2 {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        Map<Integer,Integer> map =new HashMap<>();
        for(int i=0;i<nums.length;i++){
            if(map.containsKey(nums[i]) && i-map.get(nums[i])<=k){
                return true;
            }
            map.put(nums[i],i);
        }
        return false;
    }
}
  1. Summary Ranges
    You are given a sorted unique integer array nums.
    Return the smallest sorted list of ranges that cover all the numbers in the array exactly. That is, each element of nums is covered by exactly one of the ranges, and there is no integer x such that x is in one of the ranges but not in nums.
    Each range [a,b] in the list should be output as:
    “a->b” if a != b
    “a” if a == b
Example 1:
Input: nums = [0,1,2,4,5,7]
Output: ["0->2","4->5","7"]
Explanation: The ranges are:
[0,2] --> "0->2"
[4,5] --> "4->5"
[7,7] --> "7"

index用来记录连续数组,一旦断裂或者溢出就开始记录result。继续遍历的时候i=index.

class Solution {
    public List<String> summaryRanges(int[] nums) {
        List<String> result = new ArrayList<>();
        for(int i=0;i<nums.length;i++){
            int index = i;
            while(index+1<nums.length && nums[index+1]==nums[index]+1){
                index++;
            }
            if(index==i){
                result.add(String.valueOf(nums[i]));
            }else{
                result.add(nums[i]+"->"+nums[index]);
                i=index;
            }
        }
        return result;
    }
}
  1. Missing Number

Given an array nums containing n distinct numbers in the range [0, n], return the only number in the range that is missing from the array.
Follow up: Could you implement a solution using only O(1) extra space complexity and O(n) runtime complexity?

Example 1:
Input: nums = [3,0,1]
Output: 2
Explanation: n = 3 since there are 3 numbers, so all numbers are in the range [0,3].
 2 is the missing number in the range since it does not appear in nums.

第一个是排序后遍历的直观方法,可惜排序时间复杂度要O(nlgn)

class Solution1 {
    public int missingNumber(int[] nums) {
        int n=nums.length;
        Arrays.sort(nums);
        for(int i=0;i<n;i++){
            if(i!=nums[i]){
                return i;
            }
        }
        return n;
    }
}

神奇的XOR解法又出山了,抓住missing number是落单那个。没有同类来“内部消化”。
举个栗子:nums=[0,1,3], 我们nums[]所有元素 XOR [0,n]所有元素的操作可得:

0^1^3 ^0^1^2^3 = 2
^ | 0 1      
--+-----     
0 | 0 1      
1 | 1 0    
class Solution2 {
    public int missingNumber(int[] nums) {
        int result = nums.length;
        for(int i=0;i<nums.length;i++){
            result ^= i ^ nums[i];
        }
        return result;
    }
}

还有一个方法是利用求和公式算出[0,n]之和,减去现有sums元素之和,结果就是少掉的那个元素。
在这里插入图片描述

class Solution3 {
    public int missingNumber(int[] nums) {
        int expectation = (1+nums.length)*nums.length/2;
        int sum = 0;
        for(int num:nums){
            sum+=num;
        }
        return expectation-sum;
    }
}
  1. Move Zeroes
    Given an array nums, write a function to move all 0’s to the end of it while maintaining the relative order of the non-zero elements.
    Example:
    Input: [0,1,0,3,12]
    Output: [1,3,12,0,0]
    Note:
    You must do this in-place without making a copy of the array.
    Minimize the total number of operations.
    第一个方法借助了额外的int[],虽然运行时间超越了100%,但不合要求题目要求。时间空间均为O(n)
class Solution {
    public void moveZeroes(int[] nums) {
        int[] result = new int[nums.length];
        int l=0,r=nums.length-1;
        for(int num:nums){
            if(num==0){
                result[r]=0;
                r--;
            }else{
                result[l]=num;
                l++;
            }
        }
        System.arraycopy(result, 0, nums, 0, nums.length);
    }
}

方法二是用一个满指针记录在遍历过程中将非0数存下来,再在剩下来的空位里填0.时间空间复杂度都是O(n)

class Solution {
    public void moveZeroes(int[] nums) {
        int nonZeroIndex = 0;
        for(int i=0;i<nums.length;i++){
            if(nums[i]!=0){
                nums[nonZeroIndex]=nums[i];
                nonZeroIndex++;
            }
        }
        for(int i=nonZeroIndex; i<nums.length;i++){
            nums[i]=0;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值