leetcode刷题

53 阅读5分钟

主要元素

数组中占比超过一半的元素称之为主要元素。给你一个 整数 数组,找出其中的主要元素。若没有,返回 -1 。请设计时间复杂度为 O(N) 、空间复杂度为 O(1) 的解决方案。

摩尔投票计数法。

class Solution {
    public int majorityElement(int[] nums) {
    int x=0;
    int vote=0;
    for(int num:nums){
        if(vote==0) x=num;
        vote+=num==x?1:-1;
    }
    int count=0;
    for(int num:nums){
        if(num==x) count++;
    }
    return count>nums.length/2?x:-1;
    }
}

34 在排序数组查找元素的第一个位置和最后一个位置

  • 思路 寻找左边界: mid 当num[mid]>=target 这个时候我们更新右边界,r=mid 这个时候左边可能还有相等的,所以更新右边界,因为我们是寻找最左边的元素,所以更新右边的边界,寻找右边的元素也是同理,我们更新左边界当num[mid]<=taget
class Solution 

public int[] searchRange(int[] nums, int target) {
      
    
        int[] res = new int[2];
        Arrays.fill(res, -1);
        if(nums.length<1){
            return res;
        }
        int l=0;
        int r=nums.length-1;
        
        while(l<r){
            int mid = (l+r)/2;
            if(nums[mid]>=target){
                r=mid;
            }else{
                l=mid+1;
            }
        }
        if(nums[l]==target){
            res[0]=l;
        }else{
            res[0]=-1;
        }

        l=0;r=nums.length-1;

    while(l<r){
        int mid = (l+r+1)/2;
        if(nums[mid]<=target){
            l=mid;
        }else{
            r=mid-1;
        }
    }
    
           if(nums[l]==target){
                        res[1]=l;
                                }else{
                                            res[1]=-1;
                                                    
           }
        return res;

    }
}


复原IP地址

class Solution {
    List<String> res =new ArrayList();
    public List<String> restoreIpAddresses(String s) {
        
        dfs(s,new ArrayList(),0);
        return res;
    }

    void dfs(String s,List<String> temp,int start){
    if(start==4&& s.length()==0){
        if(s.length()==0){
            res.add(String.join(".",temp));
        }
        return;
    }

        for(int i=0;i<3&&i<s.length();i++){
            if(i>0&&s.charAt(0)=='0') break;
            String s1 =s.substring(0,i+1);
            int num = Integer.parseInt(s1);
            if(num>=0&&num<=255){
                temp.add(s1);
                dfs(s.substring(i+1),temp,start+1);
                temp.remove(temp.size()-1);
            }
        }

    }

}



全排列II

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。



class Solution {

    public List<List<Integer>> permuteUnique(int[] nums) {
                List<List<Integer>> res = new ArrayList<>();

        if(nums==null|| nums.length==0) return res;
        Arrays.sort(nums);
        help(res,new ArrayList(),nums,new boolean[nums.length]);
        return res;
    }
    void help(List<List<Integer>> res,List<Integer> list,int[]nums,boolean[]used){
        if(list.size() == nums.length){
            res.add(new ArrayList(list));
            return;
        }
        for(int i=0;i<nums.length;i++){
            if(used[i]||(i>0&&nums[i]==nums[i-1]&&!used[i-1])) continue;
            list.add(nums[i]);
            used[i]=true;
            help(res,list,nums,used);
            used[i]=false;
            list.remove(list.size()-1);
        }
       
    }
}

43 字符串相乘

3
4 5 6
3* 6=18
3*5 =15+ (18中的10 1 2 3


class Solution {
    public String multiply(String num1, String num2) {
        int n1= num1.length()-1;
        int n2= num2.length()-1;
        if(n1<0||n2<0) return "";
        int[]res =new int[n1+n2+2];
        for(int i=n1;i>=0;i--){
            for(int j=n2;j>=0;j--){
               int mult = (num1.charAt(i)-'0') *(num2.charAt(j)-'0');
               mult+=res[i+j+1];
               res[i+j+1] = mult%10;
               res[i+j]+=mult/10;
            }
        }
        int index= res.length-1;
        for(int i=0;i<res.length;i++){
            if(res[i]!=0){
                index=i;
                break;
            }
        }
        StringBuilder sb = new StringBuilder();
        for(int i=index;i<res.length;i++){
            sb.append(String.valueOf(res[i]));
        }
        return sb.toString();
    }
}


1 2 2 3 

排序

    public void quickSort(int[]nums,int l,int r){
        if(l>=r){
            return;
        }
        int pivot = nums[(l+r)/2];
       int i=l;int j=r;
        while(i<=j){
            while(nums[i]<pivot) i++;
            while (nums[j]>pivot)j--;
            if(i<=j){
                int temp= nums[i];
                nums[i]=nums[j];
                nums[j]=temp;
                i++;
                j--;
            }

        }
        quickSort(nums,l,j);
        quickSort(nums,i,r);
    }
    num[i]
  为什么要i<=j为什么要

用Rand7 实现Rand10

给定方法 rand7 可生成 [1,7] 范围内的均匀随机整数,试写一个方法 rand10 生成 [1,10] 范围内的均匀随机整数。

你只能调用 rand7() 且不能调用其他方法。请不要使用系统的 Math.random() 方法。

每个测试用例将有一个内部参数 n,即你实现的函数 rand10() 在测试时将被调用的次数。请注意,这不是传递给 rand10() 的参数。



/**
 * The rand7() API is already defined in the parent class SolBase.
 * public int rand7();
 * @return a random integer in the range 1 to 7
 */
   class Solution extends SolBase {
    public int rand10() {
        int row, col, idx;
        do {
            row = rand7();
            col = rand7();
            idx = col + (row - 1) * 7;
        } while (idx > 40);
        return 1 + (idx - 1) % 10;
    }
}

 


你这个代码实现的是一个经典面试题:rand7() 生成 rand10()
我来帮你详细解释为什么这么写,以及其中的数学逻辑和优化原因👇


🌟 一、题目背景

  • 已知函数 rand7(),可以等概率生成 1~7 的整数
  • 想实现 rand10(),等概率生成 1~10 的整数
  • 关键:保证每个数字 1~10 出现概率相等

主要公式为 (rand(X)-1)Y + randY() -----生成 [1,XY]区间,并且等概。

🔍 二、代码核心逻辑

do {
    row = rand7();
    col = rand7();
    idx = col + (row - 1) * 7;
} while (idx > 40);
return 1 + (idx - 1) % 10;

1️⃣ 扩大采样空间

  • rowcol 都是 1~7:
row * col -> 7 * 7 = 49 种可能组合
  • idx = col + (row - 1) * 7
    这会把二维组合 (row, col) 映射成 1~49 的整数:
rowcol=1col=2...col=7
112...7
289...14
...............
74344...49

✅ 每个 idx 出现概率 = 1/49,完全等概率。


2️⃣ 只取前 40 个

while (idx > 40);
  • 为什么是 40 而不是 49?
    因为 40 是 10 的倍数:40 % 10 = 0,可以 平均分配给 10 个数字
  • 拒绝 idx > 40 的情况(4149),保证剩下的每个数字 140 出现概率相等(1/40)。

3️⃣ 映射到 1~10

return 1 + (idx - 1) % 10;
  • (idx-1) % 10 会映射 140 到 09:
1~10 -> 0~9 -> +1 = 1~10
11~20 -> 0~9 -> +1 = 1~10
...
31~40 -> 0~9 -> +1 = 1~10
  • 这样每个数字 1~10 出现概率 = 4/40 = 1/10 ✅ 完全等概率。

🧩 四、总结算法逻辑

  1. 二维采样:用两次 rand7() 扩大样本空间到 49 个等概率事件;
  2. 拒绝采样:只保留 140 的 idx,丢弃 4149,保证可以整除 10;
  3. 映射到目标范围:用 (idx-1) % 10 + 1 将等概率 idx 映射到 1~10。

这个方法叫 “拒绝采样(Rejection Sampling)” ,是面试中经典的从小范围随机生成大范围随机的技巧。


⚡ 五、概率保证

  • 每个 idx 1~40 出现概率 = 1/49 ÷ (40/49) = 1/40
  • 每个数字 1~10 = 4 个 idx 映射到它 → 概率 = 4/40 = 1/10 ✅