数组——6、28、30、51

6 、 旋转数组的最小数字

这种二分查找难就难在,arr[mid]跟谁比.
我们的目的是:当进行一次比较时,一定能够确定答案在mid的某一侧。一次比较为 arr[mid]跟谁比的问题。

一般的比较原则有:

  • 如果有目标值target,那么直接让arr[mid] 和 target 比较即可。
  • 如果没有目标值,一般可以考虑 端点

对于本题,非递减数组,选择右端点作为target比较好

  • 时间复杂度:二分,所以为O(logN), 但是如果是[1, 1, 1, 1],会退化到O(n)
  • 空间复杂度:没有开辟额外空间,为O(1)

low指针是最左端,high指针最右端,mid指针=low+(high-low)/2
执行前提是low<high,因为low=high则就是最终答案:{
如果low对应的数小于high对应的数,则low就是最小
如果mid大于high,一定在右端,因为此时low-mid全部大于high,所以low=mid+1,从右端搜索
否则就是mid小于high,一定在左端,所以high=mid
}

class Solution {
    public int minArray(int[] numbers) {
        int left=0,right=numbers.length-1;
        while(left<right){
            if(numbers[left]<numbers[right]) return numbers[left];
            int mid=left+(right-left)/2;
            if(numbers[mid]>numbers[right]){
                 left=mid+1;
            }
            else if(numbers[mid] == numbers[right]){
                right = right - 1;
            }
            else{
                right=mid;
            }   
        }
        return numbers[left];

    }
}
class Solution {
    public int minArray(int[] numbers) {
        int i = 0, j = numbers.length - 1;
        while (i < j) {
            int m = (i + j) / 2;
            if (numbers[m] > numbers[j]) i = m + 1;
            else if (numbers[m] < numbers[j]) j = m;
            else j--;
        }
        return numbers[i];
    }
}

python

class Solution:
    def minArray(self, numbers: [int]) -> int:
        i, j = 0, len(numbers) - 1
        while i < j:
            m = (i + j) // 2
            if numbers[m] > numbers[j]: i = m + 1
            elif numbers[m] < numbers[j]: j = m
            else: j -= 1
        return numbers[i]

解析很好

28 、 数组中出现次数超过一半的数字

sort 与 sorted 区别:
sort 只是应用在 list 上的方法,(就地排序无返回值)。
sorted 是内建函数,可对所有可迭代的对象进行排序操作,(返回新的list)

getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值。
getOrDefault() 方法的语法为:
hashmap.get(Object key, V defaultValue)

HASHMAP

import java.util.HashMap; 
public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        if(array==null)
            return 0;
        HashMap<Integer,Integer> res=new HashMap<>();
        int len = array.length;
        for(int i=0;i<array.length;i++){
            res.put(array[i],res.getOrDefault(array[i],0)+1);//意思就是当Map集合中有这个array[i]时,就使用这个array[i]对应的value值,如果没有这个array[i]就使用默认值0
            if(res.get(array[i])>len/2)
                return array[i];
        }
        return 0;
    }
}

用preValue记录上一次访问的值,count表明当前值出现的次数,如果下一个值和当前值相同那么count++;如果不同count–,减到0的时候就要更换新的preValue值了,因为如果存在超过数组长度一半的值,那么最后preValue一定会是该值。

public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        if(array == null || array.length == 0)return 0;
        int preValue = array[0];//用来记录上一次的记录
        int count = 1;//preValue出现的次数(相减之后)
        for(int i = 1; i < array.length; i++){
            if(array[i] == preValue)
                count++;
            else{
                count--;
                if(count == 0){
                    preValue = array[i];
                    count = 1;
                }
            }
        }
        int num = 0;//需要判断是否真的是大于1半数,这一步骤是非常有必要的,因为我们的上一次遍历只是保证如果存在超过一半的数就是preValue,但不代表preValue一定会超过一半
        for(int i=0; i < array.length; i++)
            if(array[i] == preValue)
                num++;
        return (num > array.length/2)?preValue:0;

    }
}

摩尔投票法

    // 摩尔投票:超过一半的数 重复相加一定大于0
    public int voteTest(int[] nums){
        int vote_cnt = 0;
        int ans = 0;
        for(int num:nums){
            if(vote_cnt == 0)
                ans = num;
            vote_cnt += ans == num?+1:-1;
        }
        return ans;
    }


    public int majorityElement(int[] nums) {
        // return hashmapTest(nums);
        // return rankTest(nums);
        return voteTest(nums);
    }
}

30、连续子数组的最大和

典型的动态规划。dp[n]代表以当前元素为截止点的连续子序列的最大和,如果dp[n-1]>0,dp[n]=dp[n]+dp[n-1],因为当前数字加上一个正数一定会变大;如果dp[n-1]<0,dp[n]不变,因为当前数字加上一个负数一定会变小。使用一个变量max记录最大的dp值返回即可

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

时间复杂度:O(n)
空间复杂度:O(n)

思想很简单,就是对下标为i的元素array[i],先试探的加上array[i], 如果和为负数,显然,以i结尾的元素对整个结果不作贡献。
具体过程:
初始化:维护一个变量tmp = 0
如果tmp+array[i] < 0, 说明以i结尾的不作贡献,重新赋值tmp = 0
否则更新tmp = tmp + array[i]
最后判断tmp是否等于0, 如果等于0, 说明数组都是负数,选取一个最大值为答案。

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array){
        int ret = array[0];
        int tmp = 0;
        for(int k:array){
            if(tmp+k<0){
                tmp=0;
                }
            else{
                    tmp +=k;
                }
                ret =Math.max(ret,tmp);
            }
        if (tmp != 0){
            return ret;
        }
        else {
            Arrays.sort(array);
            return array[array.length-1];
        }

    }
}

51、构建乘积数组

将题目拆成上三角和下三角,用递归的思想求解
参见
题解

public class Solution {
    public int[] multiply(int[] A) {
        if(A.length == 0) return new int[0];
        int[] b = new int[A.length];
        b[0] = 1;
        int tmp = 1;
        for(int i = 1; i < A.length; i++) {
            b[i] = b[i - 1] * A[i - 1];
        }
        for(int i = A.length - 2; i >= 0; i--) {
            tmp *= A[i + 1];
            b[i] *= tmp;
        }
        return b;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值