LeetCode刷题的一天(4)

LeetCode刷题的一天(4)_第1张图片

文章目录

    • 简单题·存在重复元素
      • 题目
      • 思路
      • 代码实现
    • 中等题·求众数II
      • 题目
      • 思路
      • 代码实现
    • 简单题·丑数I
      • 题目
      • 思路
    • 丑数II
      • 思路
      • 代码实现
      • 大佬的代码


今天本来要整顿一下MySQL的收藏夹,但是发现阿骨朵挺好玩的,于是。。嗯
我果断调整方向,刷上几题。
刚开始都顺风顺水的,直到第四题,那个 “中等题”。。。


简单题·存在重复元素

题目

给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。

示例 1:

输入: nums = [1,2,3,1], k = 3
输出: true

示例 2:

输入: nums = [1,0,1,1], k = 1
输出: true

示例 3:

输入: nums = [1,2,3,1,2,3], k = 2
输出: false

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/contains-duplicate-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


思路

这题,需要说吗?首先有个K的限制,很明确的告诉我们要用滑动窗口。
其次,比对已存在的值,怎么比对?轮询嘛。难不成还有更快的?

当然有啊,哈希表嘛。

然后,就完了嘛。


代码实现

bool containsNearbyDuplicate(vector<int>& nums, int k) {
     
        unordered_set<int> existed;
        int n = nums.size();
        int curr = 0;
        for (int i = 0; i < n; ++i){
     
            curr = nums[i];
            if (existed.find(curr) == existed.end()){
     
                existed.insert(curr);
                if (existed.size() > k)
                    existed.erase(nums[i-k]);                
            }
            else
                return true;            
        }
        return false;
    }

中等题·求众数II

题目

给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。

进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1)的算法解决此问题。

示例 1:

输入:[3,2,3]
输出:[3]

示例 2:

输入:nums = [1]
输出:[1]

示例 3:

输入:[1,1,1,3,3,2,2,2]
输出:[1,2]

提示:

1 <= nums.length <= 5 * 10^4
-10^9 <= nums[i] <= 10^9

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/majority-element-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


思路

怎么搞?我能想到的就,答案最多只有两个数嘛,然后呢?这个线索好像并没有什么帮助。
那就老老实实的遍历、计数嘛。

我看有种解法教做摩尔取值法,找出最有希望的答案。我还是喜欢老老实实去遍历,安全。


代码实现

vector<int> majorityElement(vector<int>& nums) {
     
        if (nums.empty()) {
     
            return {
     };
        }

        vector<int> res;
        int N = nums.size();
        unordered_map<int, int> mp;
        for (const auto& num : nums) {
     
            mp[num]++;
        }

        for (const auto& m : mp) {
     
            if (m.second > N / 3) {
     
                res.push_back(m.first);
            }
        }

        return res;
    }

简单题·丑数I

题目

编写一个程序判断给定的数是否为丑数。

丑数就是只包含质因数 2, 3, 5 的正整数。

思路

真的是简单到不能再简单了,就不讲了。

那为什么我要放这题出来?我是个极简主义者,太简单的题目我做了就当没做过。
这题不一样,这题简单的很,但是丫的进化版让我想了很久。。。


丑数II

找出第n个丑数。

注:

  1. 1是丑数
  2. 1

思路

好,现在怎么看?

这玩意儿有规律吗?有没有规律,列举一下就知道了:

1,2,3,4,5,6,8,9,10,12,15,16,18,20····

找个规律我看看啊。

找不出来的话,那就只能老老实实从头枚举到n了。

那要怎么枚举?土办法我实在是不想再想了,又烧脑又没用。
这里讲个大家都在用的三指针法。

首选,来三个指针,分别指向 2,3,5。来一个列表,纪录走过的路

开局,三个指针都指向1.
三个指针分别乘与自己指向的位置,然后,比对一下哪个小,小的那个就插进列表尾巴去。并把那个指针往前走。
如果遇上相等的,那就把那俩指针都往前一步。

别给我扯万一三个指针乘起来都相等,找一个出来呗。
重复上述步骤。

就这样,挪到列表长度为n之后,返回列表[n-1]。

抽象,别钻牛角尖,拿张纸画一遍过去就通了。


代码实现

class Solution {
     
public:
    int nthUglyNumber(int n) {
     
	if (n <= 0) {
     
		return 0;
	}

	int i = 0, j = 0, k = 0;	//三指针
	vector<int> ret;	//存储
	ret.push_back(1);	//初始哈第一个位置
	int sz = 1;	//ret的长度

	for (;sz < n;) {
     
		if (ret[i] * 2 <= ret[j] * 3 && ret[i] * 2 <= ret[k] * 5) {
     
			//如果出现相等
			if (ret[i] * 2 == ret[j] * 3)
				j++;
			else if (ret[i] * 2 == ret[k] * 5)
				k++;
			else {
     
				//选取2
				ret.push_back(ret[i] * 2);
				i++;
				sz++;
			}
		}
		else if (ret[j] * 3 <= ret[i] * 2 && ret[j] * 3 <= ret[k] * 5) {
     
			//如果出现相等
			if (ret[i] * 2 == ret[j] * 3)
				i++;
			else if (ret[j] * 3 == ret[k] * 5)
				k++;
			else {
     
				//选取3
				ret.push_back(ret[j] * 3);
				j++;
				sz++;
			}
		}
		else if (ret[k] * 5 <= ret[i] * 2 && ret[k] * 5 <= ret[j] * 3) {
     
			//如果出现相等
			if (ret[k] * 5 == ret[j] * 3)
				j++;
			else if (ret[i] * 2 == ret[k] * 5)
				i++;
			else {
     
				//选取5
				ret.push_back(ret[k] * 5);
				k++;
				sz++;
			}
		}
	}

	return ret[n-1];
}
};

大佬的代码

class Solution {
     
public:
    int nthUglyNumber(int n) {
     
        int n2(0), n3(0), n5(0);
        int *dp = new int[n];
        dp[0] = 1;
        for(int i = 1; i < n; ++i){
     
            int next2 = dp[n2]*2, next3 = dp[n3]*3, next5 = dp[n5]*5;
            if(next2 <= next3 && next2 <= next5){
     
                dp[i] = next2;
                n2++;
            }
            if(next3 <= next2 && next3 <= next5){
     
                dp[i] = next3;
                n3++;
            }
            if(next5 <= next2 && next5 <= next3){
     
                dp[i] = next5;
                n5++;
            }
        }
        return dp[n-1];
    }
};

这就是我和大佬的差距。

你可能感兴趣的:(算法/数构,leetcode,算法,哈希表,指针)