414. 第三大的数
给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。
输入:[3, 2, 1] 输出:1 解释:第三大的数是 1 。
int cmp(int* a,int* b){
return *b-*a;
}
int thirdMax(int* nums, int numsSize){
qsort(nums,numsSize,sizeof(int),cmp);
int k=1;
for(int i=1;i<numsSize; ++i){
if(nums[i]!=nums[i-1]){
k++;
if(k==3) return nums[i];// 此时 nums[i] 就是第三大的数
}
}
return nums[0];
}
594. 最长和谐子序列
和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是
1
。现在,给你一个整数数组
nums
,请你在所有可能的子序列中找到最长的和谐子序列的长度。数组的子序列是一个由数组派生出来的序列,它可以通过删除一些元素或不删除元素、且不改变其余元素的顺序而得到。
输入:nums = [1,3,2,2,5,2,3,7] 输入:nums = [1,2,3,4] 输出:5 输出:2 解释:最长的和谐子序列是 [3,2,2,2,3]
int cmp(int* a,int* b){
return *a-*b;
}
int findLHS(int* nums, int numsSize){
qsort(nums,numsSize,sizeof(int),cmp);
int l=0,r=0;
int ans=0;
//快指针
while(r<numsSize){
//慢指针状态更新
while(nums[r]-nums[l]>1){
l++;
}
//更新最值
if(nums[r]-nums[l]==1){
ans=fmax(ans,r-l+1);
}
r++;
}
return ans;
}
628. 三个数的最大乘积
给你一个整型数组
nums
,在数组中找出由三个数组成的最大乘积,并输出这个乘积。输入:nums = [1,2,3] 输入:nums = [-1,-2,3] 输出:6 输出:6
int cmp(int* a,int* b){
return *a-*b;
}
int maximumProduct(int* nums, int numsSize) {
qsort(nums,numsSize,sizeof(int),cmp);
if(numsSize<3) return 0;
//如果有负数,就取最小的两个负数以及最大正数相乘
int m1=nums[0]*nums[1]*nums[numsSize-1];
//如果是正数,就取最大的三个数
int m2=nums[numsSize-1]*nums[numsSize-2]*nums[numsSize-3];
//返回两个可疑值的最大值
return fmax(m1,m2);
}
905. 按奇偶排序数组
给你一个整数数组
nums
,将nums
中的的所有偶数元素移动到数组的前面,后跟所有奇数元素。返回满足此条件的 任一数组 作为答案。
输入:nums = [3,1,2,4] 输出:[2,4,3,1] 解释:[4,2,3,1]、[2,4,1,3] 和 [4,2,1,3] 也会被视作正确答案。
int* sortArrayByParity(int* nums, int numsSize, int* returnSize) {
int slow=0,fast=0;
while(fast<numsSize){
if(nums[fast]%2==0){
int tmp=nums[slow];
nums[slow]=nums[fast];
nums[fast]=tmp;
slow++;
}
fast++;
}
*returnSize=numsSize;
return nums;
}
922. 按奇偶排序数组 II
给定一个非负整数数组
nums
,nums
中一半整数是 奇数 ,一半整数是 偶数 。对数组进行排序,以便当
nums[i]
为奇数时,i
也是 奇数 ;当nums[i]
为偶数时,i
也是 偶数 。你可以返回 任何满足上述条件的数组作为答案 。
输入:nums = [4,2,5,7] 输出:[4,5,2,7] 解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。
int* sortArrayByParityII(int* nums, int numsSize, int* returnSize) {
int* res=malloc(sizeof(int)*numsSize);
int l=0,r=1;
for(int i=0;i<numsSize;i++){
if(nums[i]%2==0){
res[l]=nums[i];
l+=2;
}else{
res[r]=nums[i];
r+=2;
}
}
*returnSize=numsSize;
return res;
}
1005. K 次取反后最大化的数组和
给你一个整数数组
nums
和一个整数k
,按以下方法修改该数组:选择某个下标i
并将nums[i]
替换为-nums[i]
。重复这个过程恰好k
次。可以多次选择同一个下标i
。以这种方式修改数组后,返回数组 可能的最大和 。输入:nums = [4,2,3], k = 1 输出:5 解释:选择下标 1 ,nums 变为 [4,-2,3] 。
int cmp(int* a,int* b){
return abs(*b)-abs(*a);
}
int largestSumAfterKNegations(int* nums, int numsSize, int k) {
//注意排序的顺序,要按照绝对值的顺序从大到小排序
qsort(nums,numsSize,sizeof(int),cmp);
//每次从绝对值最大的值开始逆转
for(int i=0;i<numsSize;++i){
if(nums[i]<0&&k>0){
nums[i]=nums[i]*(-1);
k--;
}
}
//若遍历完数组后k还有剩余(此时所有元素应均为正),并且k为奇数时,则将绝对值最小的元素nums[numsSize-1]变为负
if(k%2==1){
nums[numsSize-1]*=-1;
}
int sum=0;
for(int i=0;i<numsSize;++i){
sum+=nums[i];
}
return sum;
}
1122. 数组的相对排序
给你两个数组,
arr1
和arr2
,arr2
中的元素各不相同,arr2
中的每个元素都出现在arr1
中。对
arr1
中的元素进行排序,使arr1
中项的相对顺序和arr2
中的相对顺序相同。未在arr2
中出现过的元素需要按照升序放在arr1
的末尾。输入:arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6] 输出:[2,2,2,1,4,3,3,9,6,7,19]
int* relativeSortArray(int* arr1, int arr1Size, int* arr2, int arr2Size, int* returnSize) {
int idx=0;
int hash[1001]={0};
for(int i=0;i<arr1Size;++i){
hash[arr1[i]]++;
}
for(int i=0;i<arr2Size;++i){
while(hash[arr2[i]]>0){
arr1[idx++]=arr2[i];
hash[arr2[i]]--;
}
}
for(int i=0;i<1001;++i){
while(hash[i]>0){
arr1[idx++]=i;
hash[i]--;
}
}
*returnSize=arr1Size;
return arr1;
}
1502. 判断能否形成等差数列
给你一个数字数组
arr
。如果一个数列中,任意相邻两项的差总等于同一个常数,那么这个数列就称为 等差数列 。
如果可以重新排列数组形成等差数列,请返回
true
;否则,返回false
。输入:arr = [3,5,1] 输出:true 解释:对数组重新排序得到 [1,3,5] 或者 [5,3,1] ,任意相邻两项的差分别为 2 或 -2 ,可以形成等差数列。
int cmp(void* a,void* b){
return *(int*)a-*(int*)b;
}
bool canMakeArithmeticProgression(int* arr, int arrSize) {
if(arrSize<=2){
return true;
}
qsort(arr,arrSize,sizeof(int),cmp);
int target=arr[1]-arr[0];
for(int i=2;i<arrSize;++i){
if(arr[i]-arr[i-1]!=target){
return false;
}
}
return true;
}
2094. 找出 3 位偶数
给你一个整数数组
digits
,其中每个元素是一个数字(0 - 9
)。数组中可能存在重复元素。
- 该整数由
digits
中的三个元素按 任意 顺序 依次连接 组成。- 该整数不含 前导零
- 该整数是一个 偶数
例如,给定的
digits
是[1, 2, 3]
,整数132
和312
满足上面列出的全部条件。将找出的所有互不相同的整数按 递增顺序 排列,并以数组形式返回。
输入:digits = [2,1,3,0] 输出:[102,120,130,132,210,230,302,310,312,320] 解释: 所有满足题目条件的整数都在输出数组中列出。 注意,答案数组中不含有 奇数 或带 前导零 的整数。
暴力法:判断每一个三位数的偶数是否能由给定的数组组成。
bool check(int num,int* flag){
int tmp[10]={0};
while(num){
int n=num%10;
tmp[n]++;
num/=10;
}
for(int i=0;i<10;++i){
if(tmp[i]>flag[i]){
return false;
}
}
return true;
}
int* findEvenNumbers(int* digits, int digitsSize, int* returnSize){
int l=0;
int* res=malloc(sizeof(int)*10000);
int flag[10]={0};
*returnSize=0;
for(int i=0;i<digitsSize;++i){
flag[digits[i]]++;
}
//判断每一个三位数的偶数是否能由给定的数组组成
for(int i=100;i<1000;i+=2){
if(check(i,flag)){
res[(*returnSize)++]=i;
}
}
return res;
}
2231. 按奇偶性交换后的最大数字
给你一个正整数
num
。你可以交换num
中 奇偶性 相同的任意两位数字(即,都是奇数或者偶数)。返回交换 任意 次之后num
的 最大 可能值。输入:num = 1234 输出:3412 解释:交换数字 3 和数字 1 ,结果得到 3214 。 交换数字 2 和数字 4 ,结果得到 3412 。 注意,可能存在其他交换序列,但是可以证明 3412 是最大可能值。注意,不能交换数字 4 和数字 1 ,因为它们奇偶性不同。
void swap(char *a,char *b){
char tmp=*a;
*a=*b;
*b=tmp;
return;
}
int largestInteger(int num) {
char* res=malloc(sizeof(char)*20);
sprintf(res,"%d",num);
int n=strlen(res);
for(int i=0;i<n;++i){
for(int j=i+1;j<n;++j){
int a=res[i]-'0';
int b=res[j]-'0';
if(a%2==0&&b%2==0&&a<b){
swap(&res[i],&res[j]);
}
if(a%2==1&&b%2==1&&a<b){
swap(&res[i],&res[j]);
}
}
}
return atoi(res);
}
2389. 和有限的最长子序列
给你一个长度为
n
的整数数组nums
,和一个长度为m
的整数数组queries
。返回一个长度为m
的数组answer
,其中answer[i]
是nums
中 元素之和小于等于queries[i]
的 子序列 的 最大 长度 。输入:nums = [4,5,2,1], queries = [3,10,21] 输出:[2,3,4] 解释:queries 对应的 answer 如下: - 子序列 [2,1] 的和小于或等于 3 。可以证明满足题目要求的子序列的最大长度是 2 ,所以 answer[0] = 2 。 - 子序列 [4,5,1] 的和小于或等于 10 。可以证明满足题目要求的子序列的最大长度是 3 ,所以 answer[1] = 3 。 - 子序列 [4,5,2,1] 的和小于或等于 21 。可以证明满足题目要求的子序列的最大长度是 4 ,所以 answer[2] = 4 。
先排序,再算前缀和,query 时只需要算最小的前缀和到哪里就可以了。
int cmp(int* a,int* b){
return *a-*b;
}
int* answerQueries(int* nums, int numsSize, int* queries, int queriesSize, int* returnSize) {
qsort(nums,numsSize,sizeof(int),cmp);
for(int i=1;i<numsSize;++i){
nums[i]+=nums[i-1];
}
int* ans=malloc(sizeof(int)*queriesSize);
for(int i=0;i<queriesSize;++i) ans[i]=0;
for(int i=0;i<queriesSize;++i){
for(int j=0;j<numsSize;++j){
if(nums[j]<=queries[i]){
ans[i]=j+1;
}
}
}
*returnSize=queriesSize;
return ans;
}
面试题 01.01. 判定字符是否唯一
实现一个算法,确定一个字符串
s
的所有字符是否全都不同。输入:
s
= "leetcode" 输出: false 输入:s
= "abc" 输出: true
bool isUnique(char* astr){
int flag[26]={0};
int n=strlen(astr);
for(int i=0;i<n;++i){
flag[astr[i]-'a']++;
}
for(int i=0;i<26;++i){
if(flag[i]>1) return false;
}
return true;
}
面试题 16.21. 交换和
给定两个整数数组,请交换一对数值(每个数组中取一个数值),使得两个数组所有元素的和相等。返回一个数组,第一个元素是第一个数组中要交换的元素,第二个元素是第二个数组中要交换的元素。若有多个答案,返回任意一个均可。若无满足条件的数值,返回空数组。
输入: array1 = [4, 1, 2, 1, 1, 2], array2 = [3, 6, 3, 3] 输出: [1, 3] 输入: array1 = [1, 2, 3], array2 = [4, 5, 6] 输出: []
暴力解法:两个for循环进行判断,但是超时。
int* findSwapValues(int* array1, int array1Size, int* array2, int array2Size, int* returnSize){
int t1=0,t2=0;
for(int i=0;i<array1Size;++i){
t1+=array1[i];
}
for(int j=0;j<array2Size;++j){
t2+=array2[j];
}
int* res=malloc(sizeof(int)*2);
*returnSize=0;
for(int i=0;i<array1Size;++i){
for(int j=0;j<array2Size;++j){
if(t1-array1[i]+array2[j]==t2-array2[j]+array1[i]){
res[0]=array1[i];
res[1]=array2[j];
*returnSize=2;
}
}
}
return res;
}
双指针
int cmp(int* a,int* b){
return *a-*b;
}
int* findSwapValues(int* array1, int array1Size, int* array2, int array2Size, int* returnSize){
qsort(array1,array1Size,sizeof(int),cmp);
qsort(array2,array2Size,sizeof(int),cmp);
int t1=0,t2=0;
for(int i=0;i<array1Size;++i){
t1+=array1[i];
}
for(int j=0;j<array2Size;++j){
t2+=array2[j];
}
int* res=malloc(sizeof(int)*2);
*returnSize=0;
if((t1-t2)%2==1) return res;
int d=t1-t2;
int i=0,j=0;
while(i<array1Size&&j<array2Size){
int cur=2*(array1[i]-array2[j]);
if(cur<d) i++;
else if(cur>d) j++;
else{
res[0]=array1[i];
res[1]=array2[j];
*returnSize=2;
return res;
}
}
return res;
}