刷题01 数组easy

        这里刷题的顺序是随机的,按标题进行筛选 ,比如今天刷的是数组有关的easy题。

 88.合并两个有序数组

        归并思想,双指针。使用一个辅助数组进行存排好后的序列。

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int *arr = (int*)malloc(sizeof(int)*(m+n));
    int index=0,left=0,right=0;
    while(index<nums1Size&&left<m&&right<n){
        if(nums1[left]<nums2[right]){
            arr[index++]=nums1[left++];
        }else if(nums1[left]>nums2[right]){
            arr[index++]=nums2[right++];
        }else{
            arr[index++]=nums1[left++];
            arr[index++]=nums2[right++];
        }
    }
    while(left<m) arr[index++]=nums1[left++];
    while(right<n) arr[index++]=nums2[right++];
    for(int i=0;i<index;i++){
        nums1[i] = arr[i];
    }
}

 136.只出现一次的数字

        注意排序的写法,遍历数组,用target记录上一个数字。

int comp(void *a,void *b){
    return *(int *)a-*(int *)b;
}
int singleNumber(int* nums, int numsSize) {
    qsort(nums,numsSize,sizeof(int),comp);//升序
    int ans=nums[0];
    for(int i=1;i<numsSize;i++){
        if(ans!=nums[i]){
            break;
        }
        i++;
        ans=nums[i];
    }
    return ans;
}

 169.多数元素

1.排序

        找数组中个数大于n/2的元素。

        由于多数的个数大于n/2,所以排序之后,如果存在多数,n/2的位置必然是多数。

int comp(void *a,void *b){
    return *(int *)a-*(int *)b;
}
int majorityElement(int* nums, int numsSize) {
    qsort(nums,numsSize,sizeof(int),comp);
    return nums[numsSize/2];
}
2.摩尔投票法 

        将第一个元素设为标志初始值,标志数量设为1,遍历元素,当元素与标志值不同时标志值--,相同时++,当标志值--时,判断标志值是否=0,等于零更换标志为nums[i],数量置1.最后返回的标志即大于n/2.

int majorityElement(int* nums, int numsSize) {
    int target=nums[0],flag=1;
    for(int i=1;i<numsSize;++i){
        if(target==nums[i]){
            flag++;
        }else{
            flag--;
            if(flag==0){
                target=nums[i];
                flag=1;
            }
        }
    }
    return target;
}

217.存在重复元素

        排序+判断

int cmp(void *a,void *b){
    return *(int*)a-*(int*)b;
}
bool containsDuplicate(int* nums, int numsSize) {
    qsort(nums,numsSize,sizeof(int),cmp);
    for(int i=1;i<numsSize;++i){
        if(nums[i-1]==nums[i]){
            return true;
        }
    }
    return false;
}

219.存在重复元素II

给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] == nums[j] 且 abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false 。

        此题涉及下标,不能进行排序,因此使用滑动窗口。

class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        unordered_set<int> s;
        int n=nums.size();
        for(int i=0;i<n;++i){
            if(i>k){
                s.erase(nums[i-k-1]);
            }
            if(s.count(nums[i])){
                return true;
            }
            s.emplace(nums[i]);
        }
        return false;
    }
};

        另一种解法,用哈希表记录每一个元素,及其下标。

class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        unordered_map<int, int> dictionary;
        int length = nums.size();
        for (int i = 0; i < length; i++) {
            int num = nums[i];
            if (dictionary.count(num) && i - dictionary[num] <= k) {
                return true;
            }
            dictionary[num] = i;
        }
        return false;
    }
};

1287.找有序数组中超过25%的元素

        注意当数组长度小于4时单独处理,不然有一些用例通不过。思路和前几题找数的题很类似。

int findSpecialInteger(int* arr, int arrSize) {
    if(arrSize<4) return arr[0];//如果数组长度小于4,又因题目说存在这个数,因此情况必然为[1]/[1,1]/[1,1,1]这三种
    int target=arr[0];
    int count=1;
    for(int i=1;i<arrSize;++i){
        if(arr[i]!=target){
            target=arr[i];
            count=1;
        }else{
            count++;
            if(count>arrSize/4){
                return target;
            }
        }
    }
    return -1;
}

1295.统计位数为偶数的数字 

        此题为简单模拟即可。

bool fun(int num){
    int count=0;
    while(num){
        num/=10;
        count++;
    }
    if(count%2==0){
        return true;
    }else{
        return false;
    }
}
int findNumbers(int* nums, int numsSize) {
    int ans=0;
    for(int i=0;i<numsSize;++i){
        if(fun(nums[i])){
            ans++;
        }
    }
    return ans;
}

1304.和为0的N个不同整数

         模拟。

int* sumZero(int n, int* returnSize){
    *returnSize=n;
    int* ans=(int *)malloc(sizeof(int)*n);
    for(int i=1;i<=n/2;++i){
        ans[i-1]=i;
        ans[n-i]=-i;//每次添加的数刚好能抵消
    }
    if(n%2==1) ans[n/2]=0;//奇数则填0
    return ans;
}

 1331.数组序号转换

        首先用一个数组保存排序完的原数组,然后用一个哈希表保存各元素的序号,最后将原属组的元素替换为序号后返回。

class Solution {
public:
    vector<int> arrayRankTransform(vector<int>& arr) {
        vector<int> sortarr=arr;
        sort(sortarr.begin(),sortarr.end());
        unordered_map<int,int> mp;//用于记录排好序后的下标值
        vector<int> ans(arr.size());
        int index=1;//记录下标
        for(int i=0;i<sortarr.size();++i){
            if(mp.count(sortarr[i])==0){//重复的值不需要记录
                mp[sortarr[i]]=index++;
            }
        }
        for(int i=0;i<arr.size();++i){
            ans[i]=mp[arr[i]];
        }
        return ans;
    }
};

1346.检查是否存在整数及其两倍的数

        直接用暴力法,两个for循环进行判断。

bool checkIfExist(int* arr, int arrSize){
    for(int i=0;i<arrSize;++i){
        for(int j=0;j<arrSize;++j){
            if(i!=j&&arr[i]==arr[j]*2){
                return true;
            }
        }
    }
    return false;
}

 1470.重新排列数组

        一次遍历,奇数和偶数下标分开赋值。

int* shuffle(int* nums, int numsSize, int n, int* returnSize){
    *returnSize=n*2;
    int *arr=(int *)malloc(sizeof(int)*n*2);
    for(int i=0;i<n;++i){
        arr[2*i]=nums[i];//偶数
        arr[2*i+1]=nums[i+n];//奇数
    }
    return arr;
}

 1528.重新排列字符串

        同上题,需要注意char[]数组需要多一位,存放‘\0’。

char* restoreString(char* s, int* indices, int indicesSize) {
    char* arr=(char*)malloc(sizeof(char)*(indicesSize+1));
    for(int i=0;i<indicesSize;++i){
        arr[indices[i]]=s[i];
    }
    arr[indicesSize]='\0';
    return arr;
}

1480.一维数组的动态和

        此题为前缀和思想的简单题。

int* runningSum(int* nums, int numsSize, int* returnSize){
    *returnSize=numsSize;
    for(int i=1;i<numsSize;++i){
        nums[i]+=nums[i-1];
    }
    return nums;
}

 1502.判断是否是等差数列

        排序,然后依次判断。

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;
}

1539.第K个缺失的数

1.数组作为哈希表

        这一解法不太好,因为如果arr中的数字太大,flag数组所占用的空间就会太大 ,但这个题中元素是三位数,所以勉强还可用这个方法。如果实在要用这个方法,就尽量把数组设置得尽量大一些,可以通过更多的测试用例。

int findKthPositive(int* arr, int arrSize, int k){
    int flag[3000]={0};
    for(int i=0;i<arrSize;++i){
        flag[arr[i]]=1;
    }
    for(int i=1;i<3000;++i){
        if(flag[i]==0){
            k--;
        }
        if(k==0){
            return i;
        }
    }
    return arr[arrSize-1]+1;
}
2.枚举 

        该解法比较直观,注意一些细节。

int findKthPositive(int* arr, int arrSize, int k){
    int cur=1,p=0,misscount=0,lastmiss=-1;
    //cur是当前应该出现的数
    //p指向数组中没有匹配的第一个元素
    //misscount是缺失的数的个数
    //lastmiss是最后一个缺失的数
    for(misscount=0;misscount<k;cur++){
        if(cur==arr[p]){
            if(p+1<arrSize){//p大于数组长度时,p不再增加
                p++;
            }
        }else{
            misscount++;
            lastmiss=cur;
        }
    }
    return lastmiss;
}

1550.存在连续三个奇数的数组

         枚举长度为3的子序列,依次判断即可。

bool threeConsecutiveOdds(int* arr, int arrSize) {
    for(int i=2;i<arrSize;++i){
        if(arr[i]%2==1&&arr[i-1]%2==1&&arr[i-2]%2==1){
            return true;
        }
    }
    return false;
}

 1588.所有奇数长度子数组的和

        1.暴力解

        模拟,需要注意的是for循环的边界条件。

int sumOddLengthSubarrays(int* arr, int arrSize){
    int sum=0;
    //枚举奇数
    for(int i=1;i<=arrSize;i+=2){
        for(int k=0;k<=arrSize-i;++k){
            for(int j=k;j<k+i;++j){
                sum+=arr[j];
            }
        }
    }
    return sum;
}
         2.前缀和

        用一个数组进行计算子数组的前缀和。然后再枚举子数组的起始位置和终止位置。

int sumOddLengthSubarrays(int* arr, int arrSize){
    int prefixsum[arrSize+1];
    prefixsum[0]=0;
    for(int i=0;i<arrSize;++i){
        prefixsum[i+1]=prefixsum[i]+arr[i];
    }
    int sum=0;
    for(int start=0;start<arrSize;++start){//枚举起始位置
        for(int length=1;start+length<=arrSize;length+=2){//枚举子数组长度
            int end=start+length-1;
            sum+=prefixsum[end+1]-prefixsum[start];//每次加上子数组之和
        }
    }
    return sum;
}

 1608.特殊数组的特征值

给你一个非负整数数组 nums 。如果存在一个数 x ,使得 nums 中恰好有 x 个元素 大于或者等于 x ,那么就称 nums 是一个 特殊数组 ,而 x 是该数组的 特征值 。

注意: x 不必 是 nums 的中的元素。

         暴力解法,注意两处细节即可。

int specialArray(int* nums, int numsSize){
    for(int i=0;i<=numsSize;++i){//枚举x的值,可以等于numsSize
        int count=0;
        for(int j=0;j<numsSize;++j){
            if(nums[j]>=i){
                count++;
            }
        }
        if(count==i) return i;//恰好等于,所以必须在循环外面判断
    }
    return -1;
}

  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值