2021-11-29 力扣169,287,162

169. 多数元素

方法一:利用哈希表来找出现次数大于n/2的元素,没有啥难度

class Solution {
    public int majorityElement(int[] nums) {
        //根据题意一定要分析出多数元素一个数组中只能有一个数
        int n = nums.length;
        int num = 0;
        Map<Integer,Integer> map = new HashMap<>();
        for(int x: nums){
            map.put(x,map.getOrDefault(x,0)+1);
            if(map.get(x) > n/2){
               num = x;
           }
        }
        return num;
    }
}

方法二:新思想:

摩尔投票法思路
候选人(cand_num)初始化为nums[0],票数count初始化为1。
当遇到与cand_num相同的数,则票数count = count + 1,否则票数count = count - 1。
当票数count为0时,更换候选人,并将票数count重置为1。
遍历完数组后,cand_num即为最终答案。

为何这行得通呢?
投票法是遇到相同的则票数 + 1,遇到不同的则票数 - 1。
且“多数元素”的个数> ⌊ n/2 ⌋,其余元素的个数总和<= ⌊ n/2 ⌋。
因此“多数元素”的个数 - 其余元素的个数总和 的结果 肯定 >= 1。
这就相当于每个“多数元素”和其他元素 两两相互抵消,抵消到最后肯定还剩余至少1个“多数元素”。

class Solution {
    public int majorityElement(int[] nums) {
        int x = nums[0];
        int count = 1;
        for(int i=1;i<nums.length;i++){
            if(x == nums[i]){
                count++;
            }else{
                count--;
            }
            if(count == 0){ 
            x = nums[i];
            //卡在这一步,换数后忘了再把count也重新赋值为1
            count = 1;
            }
        }
        return x;
    }
}
287. 寻找重复数

方法一:无脑暴力法

class Solution {
    public int findDuplicate(int[] nums) {
        int num = nums[0];
        Arrays.sort(nums);
        for(int i=0;i<nums.length-1;i++){
            if(nums[i] == nums[i+1]){
                num = nums[i];
            }
        }
        return num;
    }
}

方法二:函数思想

class Solution {
    public int findDuplicate(int[] nums) {
    //将题目给的特殊的数组当作一个链表来看,数组的下标就是指向元素的指针,把
    //数组的元素也看作指针。如 0 是指针,指向 nums[0],而 nums[0] 也是针, 
    //指向 nums[nums[0]].
    int fast = 0;
    int slow = 0;
    int c = 0;
        while(true){
         //   nums[fast] = nums[nums[fast]];
         fast = nums[nums[fast]];//快指针,相当于 .next.next
         slow = nums[slow]; //慢指针,相当于.next
            if(fast == slow){
                break;
            }

        }
        //难点:找到重合后清零然后同步走
        while(nums[c] != nums[slow]){
            c = nums[c];
            slow = nums[slow];
        }
        return nums[slow];
    }
}
162. 寻找峰值
class Solution {
    public int findPeakElement(int[] nums) {
        int left = 0;
        int right = nums.length-1;
        while(left < right){
            int mid = left + (right - left)/2;
            if(nums[mid] > nums[mid+1]){
                //right = mid-1;
                //right可能就是峰顶
                right = mid;
            }else{
                left = mid+1;
            }
        }
        return left; 
    }
}

思路:
爬山,如果你往下坡方向走,也许可能遇到新的山峰,但是也许是一个一直下降的坡,最后到边界。但是如果你往上坡方向走,就算最后一直上的边界,由于最边界是负无穷,所以就一定能找到山峰,总的一句话,往递增的方向上,二分,一定能找到,往递减的方向只是可能找到,也许没有。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值