主要元素
数组中占比超过一半的元素称之为主要元素。给你一个 整数 数组,找出其中的主要元素。若没有,返回 -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中的1)
0 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️⃣ 扩大采样空间
row和col都是 1~7:
row * col -> 7 * 7 = 49 种可能组合
idx = col + (row - 1) * 7
这会把二维组合(row, col)映射成 1~49 的整数:
| row | col=1 | col=2 | ... | col=7 |
|---|---|---|---|---|
| 1 | 1 | 2 | ... | 7 |
| 2 | 8 | 9 | ... | 14 |
| ... | ... | ... | ... | ... |
| 7 | 43 | 44 | ... | 49 |
✅ 每个 idx 出现概率 = 1/49,完全等概率。
2️⃣ 只取前 40 个
while (idx > 40);
- 为什么是 40 而不是 49?
因为 40 是 10 的倍数:40 % 10 = 0,可以 平均分配给 10 个数字。 - 拒绝 idx > 40 的情况(41
49),保证剩下的每个数字 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 ✅ 完全等概率。
🧩 四、总结算法逻辑
- 二维采样:用两次
rand7()扩大样本空间到 49 个等概率事件; - 拒绝采样:只保留 1
40 的 idx,丢弃 4149,保证可以整除 10; - 映射到目标范围:用
(idx-1) % 10 + 1将等概率 idx 映射到 1~10。
这个方法叫 “拒绝采样(Rejection Sampling)” ,是面试中经典的从小范围随机生成大范围随机的技巧。
⚡ 五、概率保证
- 每个
idx1~40 出现概率 = 1/49 ÷ (40/49) = 1/40 - 每个数字 1~10 = 4 个 idx 映射到它 → 概率 = 4/40 = 1/10 ✅