LeetCode(Top Interview Questions)——Array

本文深入解析LeetCode上的五个经典算法题,包括去除数组重复项、最佳股票买卖时机、数组旋转、查找重复元素及寻找唯一元素,提供高效代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(一)Remove Duplicates from Sorted Array

 Given a sorted array nums, remove the duplicates in-place such that each
  element appear only once 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.
  • 要求:剔除有序数组中的重复值。

  • 思想:将已经去重的元素保存在数组的前半部分。遍历后续的每一个元素并与已去重部分的最大元素比较,如果相等则无操作继续遍历,如果不等则将此元素保存在已去重部分。

  • code:

public int removeDuplicates(int[] nums) {
        int length=1;
        for(int i=1;i<nums.length;i++){
            if (nums[i]!=nums[length-1]){
                nums[length]=nums[i];
                length++;
            }

        }
        return length;
    }
  • 如果数组是无序的,则需与已去重部分逐一比较。这个效率较低。(当然也可以先排序)
public int removeDuplicates(int[] nums) {
        int length=1;
        for(int i=1;i<nums.length;i++){
            for(int j=0;j<length;j++){
                if (nums[i]==nums[j]) break;
                else if (j==length-1) { nums[length]=nums[i];length++; }
            }
        }
        return length;
    }

(二)Best Time to Buy and Sell Stock II

Say you have an array 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.
Example 2:

Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
             Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
             engaging multiple transactions at the same time. You must sell before buying again.
Example 3:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
  • 要求:数组值为股票价格,下标对应日期,股票可以多次买卖,但不可以同一天既买又卖。找出最大利润。
  • 思想:因为可以多次买卖,所以找出相邻股票价格的最大上升趋势,这便是一次合适的买卖。
  • code
 public int maxProfit(int[] prices) {
        int total=0;
        for (int i=0;i<prices.length-1;i++) {
            if (prices[i+1]>prices[i]) total+=prices[i+1]-prices[i];
        }
        return total;
    }
  • 这是效率最高的代码,有人说这违反了题目中不能同一天买卖的要求,其实可以理解为每天都计算一次当日利润,盈利则算在总收入之中,亏损则无操作,相当于昨天已经卖掉。然后继续等待下一次盈利时计算利润,就假装是买入了。
  • 如果非要较真的话,也可以尝试这个解决方案:
public int maxProfit(int[] prices) {
    int profit = 0, i = 0;
    while (i < prices.length) {
        // find next local minimum
        while (i < prices.length-1 && prices[i+1] <= prices[i]) i++;
        int min = prices[i++]; // need increment to avoid infinite loop for "[1]"
        // find next local maximum
        while (i < prices.length-1 && prices[i+1] >= prices[i]) i++;
        profit += i < prices.length ? prices[i++] - min : 0;
    }
    return profit;
}

(三)Rotate Array

  • 问题描述:将数组元素按步长右移,步长非负(要求空间复杂度为O(1))
Given an array, rotate the array to the right by k steps, where k is non-negative.

Example 1:

Input: [1,2,3,4,5,6,7] and k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]
Example 2:

Input: [-1,-100,3,99] and k = 2
Output: [3,99,-1,-100]
Explanation: 
rotate 1 steps to the right: [99,-1,-100,3]
rotate 2 steps to the right: [3,99,-1,-100]
Note:

Try to come up as many solutions as you can, there are at least 3 different ways to
 solve this problem.
Could you do it in-place with O(1) extra space?
  • 解决方案:先将数组整体翻转,再按步长部分翻转
public  void rotate(int[] nums, int k) {
        k=k%nums.length;
        reverse(nums,0,nums.length-1);
        reverse(nums,0,k-1);
        reverse(nums,k,nums.length-1);

    }


    public   void reverse(int[] nums,int start ,int end){
        while(start<end){
            int temp=nums[start];
            nums[start]=nums[end];
            nums[end]=temp;
            start++;
            end--;
        }
    }

(四)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
Example 2:

Input: [1,2,3,4]
Output: false
Example 3:

Input: [1,1,1,3,3,4,3,2,4,2]
Output: true
  • 如果题目限定了数组中整数的取值范围,可以拿空间换时间。如下:
public static boolean containsDuplicate(int[] nums) {
        int[] flag=new int[10000];
        int[] negative_flag=new int[10000];
        for (int i:nums) {
            if (i<0){
                int a=Math.abs(i);
                if (negative_flag[a]==1) return true;
                else negative_flag[a]=1;
            }else{
                if (flag[i]==1) return true;
                else flag[i]=1;
            }

        }
        return false;
    }

  • 如果没有限定数组中整数的取值范围,则:
public static boolean containsDuplicate(int[] nums) {
		//使用java库函数将数组排序
        Arrays.sort(nums);
        //遍历数组,比较相邻元素即可
        for (int i=1;i<nums.length;i++){
            if (nums[i]==nums[i-1]) return true;
        }
        return false;
    }

(五)Single Number

  • 问题描述:给定非空数组,数组中每个元素均出现两次,只有一个元素出现了一次,找出那个元素。
Given a non-empty array of integers, every element appears twice except for one. 
Find that single one.

Note:

Your algorithm should have a linear runtime complexity. Could you implement it without 
using extra memory?

Example 1:

Input: [2,2,1]
Output: 1
Example 2:

Input: [4,1,2,1,2]
Output: 4
  • 我的答案(本以为和上次的问题解法相似):时间复杂度太高。
public static int  singleNumber(int[] nums) {

        Arrays.sort(nums);
        for (int i=0;i<nums.length-1;i+=2){
            if (nums[i]!=nums[i+1]) return nums[i];
        }
        return nums[nums.length-1];
    }
  • 大神的答案:将数组的数进行异或运算。
int singleNumber(int A[], int n) {
    int result = 0;
    for (int i = 0; i<n; i++)
    {
		result ^=A[i];
    }
	return result;
}
补充知识点:
	A^A=0
	0^A=A
	==异或符合交换律==、==异或符合结合律==
	
解释:假设有数组[2,1,2],异或后为 2 ^ 1 ^ 2,即(2 ^ 2)^ 1=0 ^ 1=1。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值