【每日刷题3.11】10道算法+10道面试 - 阿V

加油加油,13号阿里笔试,冲冲冲!

算法题(英雄哥九日集训-第五天)

1. 排序数组

 任何一种排序都可以。这里我用了快速排序,但快排是一种不稳定的排序方式,所以为了避免最坏的情况出现,快排前都要将数组打乱。


代码详情:

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        int n = nums.size();
        for(int i = 0;i < n; ++i){ //打乱数组
            int j = rand() % (nums.size());
            
            swap(nums[i], nums[j]);
        }

        helper_quicksort(nums,0,n-1); 
        return nums;
    }

    //快排辅函数
    void helper_quicksort(vector<int>& nums,int l, int r){
        if(l < r){
            int pos = quicksort(nums,l,r); //快排当前数组
            helper_quicksort(nums,l,pos - 1); //快排左部分
            helper_quicksort(nums,pos + 1,r); //快排右部分
        }
    }


    //快排函数
    int quicksort(vector<int>& nums,int l, int r){
        int i = l + 1,j = r;
        while(i <= j){
            while(i <= r && nums[i] <= nums[l]){ //寻找小于nums[l]的数
                ++i;
            }
            while(j > l && nums[j] > nums[l]){ //寻找大于nums[l]的数
                --j;
            }
            if (i >= j){
                break;
            }
            swap(nums[i],nums[j]); //交换
        }
        swap(nums[l],nums[j]); //将基数换到正确位置

        return j; //返回正确位置
    }
};

通过情况:

2.  多数元素

 之前写过,用的是选举者算法。


代码详情:

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int n = nums.size();
        int maxnum = nums[0],size = 1; //选举者算法

        for(int i = 1; i < n; ++i){
            if (nums[i] != maxnum){ //投票人不赞同
                size--; //票数减一
                if (size < 1 && i < n){ //票数归零,重新选举
                    size = 1;
                    maxnum = nums[++i];
                } 
            }
            else{ //投票人赞同
                size++;
            }
        }

        return maxnum;
    }
};  

通过详情:

 3. 存在重复元素

 使用哈希表边遍历边保存,查看是否有重复数据。


代码详情:

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        int n = nums.size();
        if (n < 2) return false; //边界判断
        unordered_set<int> set; //创建哈希表

        for(int i = 0;i < n;++i){
            if(set.count(nums[i])){ //查看之前是否有相同的数
                return true;
            }
            set.emplace(nums[i]); //压入哈希表
        }

        return false;
    }
};

 通过情况:

 4. 最大间距

 一开始我直接使用了sort函数,但发现sort函数本质是快排,时间复杂度为O(nlogn)不符合题目线性时间条件。这里学习了新的排序---基数排序。


代码详情:

class Solution {
public:
    int maximumGap(vector<int>& nums) {
        int n = nums.size();
        if (n < 2) return 0; //边界情况
        
        //基数排序
        int maxnum = *max_element(nums.begin(), nums.end()); //获取最大值
        int exp = 1;
        while(maxnum >= exp){
            vector<int> buf(10,0); //创建桶
            for(int i = 0;i < n; ++i){ //分好桶
                int j = (nums[i] / exp) % 10;
                buf[j]++;
            }
            for (int i = 1;i < 10; ++i){ //计算每个位置前有多少个数
                buf[i] += buf[i-1];
            }

            int k = 0; //nums数组下标
            vector<int> tem(n); //创建临时数组
            for(int i = n - 1;i >= 0; --i){ //重新构造数组
                int j = (nums[i] / exp) % 10;
                tem[--buf[j]] = nums[i];
            }
            nums = tem;
            exp *= 10;
        }


        int maxsize = 0; //存储最大间隔
        for (int i = 1; i < n; ++i){ //逐个遍历最大间隔
            maxsize = max(maxsize,nums[i] - nums[i-1]);
        }

        return maxsize;
    }
};

 通过情况:

 5. 按奇偶排序数组

 一开始我只用了左指针来保存偶数数组下标,看了题解发现用左右指针双向遍历更快。


 代码详情:

class Solution {
public:
    vector<int> sortArrayByParity(vector<int>& nums) {
        int n = nums.size();
        int left = 0, right = n - 1; //创建个指向偶数下标的指针

        while(left < right){
            while(left < right && nums[left] % 2 == 0){ //寻找非偶数
                ++left;
            }
            while(right > left && nums[right] % 2 == 1){ //同理
                --right;
            }
            if (left >= right){
                break;
            }
            swap(nums[left],nums[right]);
        }

        return nums;
    }
};

通过情况:

6.  最小时间差

有两个注意的点,一个是时间差最多不超过720分钟,第二个就是遍历的时候容易把头尾忘掉。


代码详情:

class Solution {
public:
    int findMinDifference(vector<string>& timePoints) {
        sort(timePoints.begin(),timePoints.end()); //将时间排好序
        int n = timePoints.size();

        int mintime = 12*60; //最长只可能是12*60分钟
        for(int i = 1; i <= n; ++i){
            int pre = changetime(timePoints[(i-1) % n]);
            int now = changetime(timePoints[i % n]);
            int time = abs(pre-now);
            int timesize = time <= 720 ? time : 1440-time; //判断哪边时间差更小
            mintime = min(mintime, timesize);
        }

        return mintime;
    }

    //转换分钟函数
    int changetime(string str){
        cout << (str[0]-'0')*10*60 + (str[1]-'0')*60 + (str[3]-'0')*10 + (str[4]-'0') << endl;
        return (str[0]-'0')*10*60 + (str[1]-'0')*60 + (str[3]-'0')*10 + (str[4]-'0');
    }
};

通过详情:

7. 三角形的最大周长 

 我有思考到贪心算法,但没想明白,一看他人代码就秒懂了。


代码详情:

class Solution {
public:
    int largestPerimeter(vector<int>& nums) {
        sort(nums.begin(),nums.end());

        for(int i = nums.size() - 1; i > 1; --i){
            if (nums[i-2] + nums[i-1] > nums[i]){ //三角形任意两边之和大于第三边
                return nums[i-2] + nums[i-1] + nums[i];
            }
        }

        return 0;
    }
};

 通过情况:

 8. 救生艇

 贪心算法。


代码详情:

class Solution {
public:
    int numRescueBoats(vector<int>& people, int limit) {
        int n = people.size();
        sort(people.begin(),people.end());

        int boats = 0; //记录船数
        int left = 0, right = n-1; //创建左右指针
        while(left <= right){
            if (people[left] + people[right] <= limit){ //同时放入最重和最小的人
                ++left,--right;
            }
            else{ //放不下就只放最重的
                --right;
            }
            ++boats;
        }

        return boats;
    }
};

 通过详情:

后天就要笔试阿里了,脑子却有点不活跃,休息一下,明天继续加油!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZZW游戏制造

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值