2021-10-26每日刷题打卡

2021-10-26每日刷题打卡

力扣——每日一题

496. 下一个更大元素 I

给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。

请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。

nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。

示例 1:

输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
对于 num1 中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 -1 。
对于 num1 中的数字 1 ,第二个数组中数字1右边的下一个较大数字是 3 。
对于 num1 中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 -1 。

这题有两个方法,第一种节省空间但速度慢,第二种速度快但占用空间较多

第一种:创建一个vector容器v来存放结果,直接for遍历nums1,里面再放上一个for用来遍历nums2,每次遍历nums1新的元素时去nums2里找到和当前nums1相同的元素,找到以后继续遍历,如果有大于它的数就把那个数插入v中并break结束循环,如果没有大于他的数就插入一个-1。当nums1遍历完后结束循环,返回v即可

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        vector<int>v;
        int n=nums1.size(),m=nums2.size();
        bool b=false;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(b&&nums2[j]>nums1[i])
                {
                    v.push_back(nums2[j]);
                    break;
                }
                if(nums1[i]==nums2[j])
                {
                    b=true;
                }
            }
            b=false;
            if(v.size()==i)
            {
                v.push_back(-1);
            }
        }
        return v;
    }
};

第二种:要用上map、stack的知识,准备一个unordered_map容器mymap,一个stack容器sta,一个vector容器v。先遍历nums2,从最后一个元素开始遍历,每次遍历判断栈sta顶部元素是否小于当前元素,如果小于就持续出栈,知道栈为空或顶端元素大于当前遍历元素,然后mymap开始记录当前元素之后有无最大值,mymap[nums2[i]]==sta.empty?-1:sta.top(),这里意思是,如果栈为空,说明我们之前遍历过的元素没有大于当前元素的(因为都在前面出栈弹掉了),如果栈不为空,就说明栈顶元素是大于我们当前元素的,把这个元素赋给mymap,事后要将当前元素入栈。遍历完后开始遍历nums1,每次经由mymap[nums[i]]获知当前元素之后有没有大于它的元素。把结果插入v中。最后返回v

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        unordered_map<int,int>mymap;
        stack<int>sta;
        vector<int>v;
        int n=nums1.size();
        for(int i=nums2.size()-1;i>=0;i--)
        {
            int num = nums2[i];
            while(!sta.empty()&&sta.top()<num)
            {
                sta.pop();
            }
            mymap[num]=sta.empty()?-1:sta.top();
            sta.push(num);
        }
        for(int i=0;i<n;i++)
        {
            v.push_back(mymap[nums1[i]]);
        }
        return v;
    }
};
189. 旋转数组

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

进阶:

尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]

原本试了下看看能不能把O(1)的算法写出来,结果超时了。。。我还是写简单的吧

准备一个vector容器v,遍历一遍nums,每次在v的(i+k)%nums.size() 位置上放上nums[i]的值(%nums.size()是为了防止数组越界,同时把旋转后的数插入v前面的位置上。),但由于这里没有返回值,是要修改nums里的值,所以我们遍历一遍v把值复制给nums。

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n=nums.size();
        vector<int>v(n);
        for(int i=0;i<n;i++)
        {
            v[(i+k)%n]=nums[i];
        }
        for(int i=0;i<n;i++)
        {
            nums[i]=v[i];
        }
    }

};

第二个方法,利用队列queue来进行旋转操作(出队后入队)。准备一个queue容器que,将nums从尾部数据开始依次入队que(先进先出),然后把队头元素出队再入队,一个进行k次,之后队列里的位置就是旋转好的序列了,再把que的数据复制在nums里即可。

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        queue<int>que;
        int n = nums.size();
        int m = k % n;
        for(int i=n-1;i>=0;i--)
        {
            que.push(nums[i]);
        }
        while(m--)
        {
            int num=que.front();
            que.pop();
            que.push(num);
        }
        for(int i=n-1;i>=0;i--)
        {
            nums[i]=que.front();
            que.pop();
        }
    }

};
283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:

必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。

尽量减少不知道咋减少。。。嘛反正是没用额外的数组。

准备两个指针l和r,初始都为0,用两个指针来遍历nums,当l或r大于等于nums.size()时结束循环,如果l当前指向的位置数不为0,则l和r同时++,如果l指向的位置数为0,则r往前移动,直到nums[r]不为0,然后交换l和r位置上的元素(这里要注意r可能会超出nums.size(),所以要加判断如果r大于等于nums.size()就结束循环)。

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
    int l = 0, r = 0, n = nums.size();
    while (r < n)
    {
        if (nums[l] != 0)
        {
            l++;
            r++;
        }
        else
        {
            while (r < n&&nums[r] == 0 )
            {
                r++;
                
            }
            if (r >= n)
            {
                break;
            }
            int math = nums[l];
            nums[l] = nums[r];
            nums[r] = math;
        }
    }
}
};
167. 两数之和 II - 输入有序数组

给定一个已按照 非递减顺序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。

函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。

你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

示例 1:

输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

双指针写法,因为这数组是递增的,所以我们可以用头尾双指针来写,一个left=0,一个right=numbers.size()-1,一个vector容器v,开始遍历,每次判断numbers[left]+numbers[right]的值,如果等于目标值就把left和right插入v中,break掉循环并返回v。如果大于目标值,说明number[right]的值过大(总不能是left太大,人家已经最小了),把right–以减小numbers[right]的值。如果小于目标值说明numbers[left]的值过下,把left++。

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        int i=0,j=numbers.size()-1;
        vector<int>v;
       while(i<j)
       {
           if(numbers[i]+numbers[j]==target)
           {
               v.push_back(i+1);
               v.push_back(j+1);
               break;
           }
           else if(numbers[i]+numbers[j]>target)
           {
               j--;
           }
           else
           {
               i++;
           }
       }
        return v;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值