『LeetCode』《算法面试题汇总》p1——开始之前

136.只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例:

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

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

很简单,想想异或,解法如下:

int singleNumber(vector<int>& nums) {
    int res = 0;
    for (int num: nums)
        res ^= num;
    return res;
}

169.多数元素

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例:

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

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

刚看这道题的时候还是一头雾水,看了题解才恍然大悟,原来早就有很巧妙的解法了,即摩尔投票算法,代码如下所示,原理也很简单,一看就懂,但若要我自己想出来,怕是不太可能咯。

int majorityElement(vector<int>& nums) {
    int candidate = 0;
    int cnt = 0;
    for (int i = 0; i < nums.size(); ++i) {
        if (cnt == 0) {
            candidate = nums[i];
            ++cnt;
        } 
        else if (nums[i] == candidate)
            ++cnt;
        else
            --cnt;
    }
    return candidate;
}

240.搜索二维矩阵 II

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

  • 每行的元素从左到右升序排列。
  • 每列的元素从上到下升序排列。

示例2:
示例

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
输出:true

解法很直观,我原先的解法还复杂了,非要弄个二分查找,其实得不偿失,直接搜索也挺好的,时间复杂度最多也就是 \(O(m+n)\),自以为习得了新的了不起的知识,反而把最基本的东西抛弃了,实在不应该。

这种直观解法的思路即从矩阵的右上角开始寻找,如果当前元素比 target 大,那么比较当前行的前一个元素,如果当前元素比 target 小,那么比较当前列的下一个元素,直到超出边界。

bool searchMatrix(vector<vector<int>>& matrix, int target) {
    int m = matrix.size();
    int n = matrix[0].size();
    // find from top right
    int i = 0;
    int j = n-1;
    while (i < m && j >= 0) {
        if (target == matrix[i][j])
            return true;
        else if (matrix[i][j] > target)
            --j;
        else
            ++i;
    }
    return false;
}

88.合并两个有序数组

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。

初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。

示例:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]

输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]

这也是一道经典题了,百试不厌,挺简单的,这个是合并数组,类似的还有合并链表,甚至都可以用同一个模板,这都是基础。

void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
    int tail = m + n -1;
    --m;
    --n;
    while (m >= 0 && n >= 0) {
        if (nums1[m] > nums2[n])
            nums1[tail--] = nums1[m--];
        else
            nums1[tail--] = nums2[n--];
    }
    while (n >= 0)
        nums1[tail--] = nums2[n--];
    return;
}

887.鸡蛋掉落

你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N  共有 N 层楼的建筑。
每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去。
你知道存在楼层 F ,满足 0 <= F <= N 任何从高于 F 的楼层落下的鸡蛋都会碎,从 F 楼层或比它低的楼层落下的鸡蛋都不会破。
每次移动,你可以取一个鸡蛋(如果你有完整的鸡蛋)并把它从任一楼层 X 扔下(满足 1 <= X <= N)。
你的目标是确切地知道 F 的值是多少。
无论 F 的初始值如何,你确定 F 的值的最小移动次数是多少?

示例:

输入:K = 2, N = 6
输出:3
-
输入:K = 3, N = 14
输出:4

好难啊,看了题解才知道自己实在是太菜了,好好研究下题解吧。

posted on 2021-02-19 23:44  mkd1rFailed  阅读(33)  评论(0编辑  收藏  举报