【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;
        }
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值