【LeetCode】Algorithms 題集(九)

Product of Array Except Self 

題意:

Given an array of n integers where n > 1, nums, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i].

Solve it without division and in O(n).

For example, given [1,2,3,4], return [24,12,8,6].


Follow up:

Could you solve it with constant space complexity? (Note: The output array does not count as extra space for the purpose of space complexity analysis.)

思路:

    不可以使用除法,用 O(n) 的時間,用常量的空間。先在結果數組裏從右往左計算,每個 ans[i] 等於它右邊的數連乘的結果。然後從左往右處理,一個臨時變量保存到目前爲止左邊的數連乘的結果,更新 ans[i], 更新臨時變量。

代碼:

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> ans(n, 1);
        
        for (int i = n-2; i >= 0; --i) {
            ans[i] = ans[i+1] * nums[i+1];
        }
        
        int left = 1;
        for (int i = 0; i < n; ++i) {
            ans[i] *= left;
            left *= nums[i];
        }
        
        return ans;
        
    }
};


Nim Game

題意:

You are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones.


Both of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap.


For example, if there are 4 stones in the heap, then you will never win the game: no matter 1, 2, or 3 stones you remove, the last stone will always be removed by your friend.

思路:

     輪流取石子游戲,每次只能取 1 到 3 個,兩個人都是最優策略,誰取到最後一個就贏了。判斷能夠勝利的依據是當面對 4 的倍數時,一定會輸,其他情況一定可以贏,因爲其他情況可以通過拿走 1 到 3 個石子讓對手面對 4 的倍數。

代碼:

class Solution {
public:
    bool canWinNim(int n) {
        if (n % 4 == 0) return false;
        else return true;
    }
};

Move Zeroes

題意:

Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements.


For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [1, 3, 12, 0, 0].


Note:

You must do this in-place without making a copy of the array.

Minimize the total number of operations.

思路:

     把所有非 0 數排到前面,順序不變,所有 0 “擠" 到數組後面。想法是一遇到非零數就往前放,放的位置是當前未被重組後的非零數字佔據的位置,也就是維持一個結果數組的當前下標,一遇到非零數就往那個下標放,然後更新下標。最後把後面的位置都清爲 0 。這樣是 O(n) 的時間,沒有多餘空間。

代碼:
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int cur = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] != 0) {
                if (cur != i) nums[cur] = nums[i];
                cur++;
            }
        }
        for (int i = cur;i < nums.size(); i++) {
            nums[i] = 0;
        }
    }
};

Invert Binary Tree

題意:

Invert a binary tree.

     4
   /   \
  2     7
 / \   / \
1   3 6   9
to
     4
   /   \
  7     2
 / \   / \
9   6 3   1
Trivia:
This problem was inspired by this original tweet by Max Howell:
Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so fuck off.
思路:

     大名鼎鼎的反轉二叉樹,其實,把白板翻過來就好了。。。


代碼:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == NULL || root->left == NULL && root->right == NULL) return root;
        
        invertTree(root->left);
        invertTree(root->right);
        
        TreeNode* tmp = root->left;
        root->left = root->right;
        root->right = tmp;
        
        return root;
    }
};

Missing Number

題意:

Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array.


For example, Given nums = [0, 1, 3] return 2.


Note:

Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?

思路:

     首先要注意輸入是無序的。題意說的是找出從 0, 1, 2 .... n 這個序列中少的那個數,很自然的想法是算 0 到 n 的和,然後減去數組中的和,得到的差就是少了的數,但是相減有可能得 0,這時候可能是數組中 少了 0,即 1, 2, 3,...,n,或者數組中少了 n, 即 0, 1, 2, 3,...., n-1,區分很容易,只要看數組中最小的數是不是 0 就好了。

代碼:

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int res = 0;
        int maxNums = -1;
        int minNums = 0x7fffffff;
        for (int i = 0; i < nums.size(); ++i) {
            res += nums[i];
            if (nums[i] > maxNums) maxNums = nums[i];
            if (nums[i] < minNums) minNums = nums[i];
        }
        
        int cacu = (maxNums + 1)*maxNums/2;
        if (cacu != res) {
            return cacu - res;
        } else {
            if (minNums == 0) return maxNums + 1;
            else return 0;
        }
    }
};

發佈了123 篇原創文章 · 獲贊 268 · 訪問量 111萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章