Tag Archives: 数学

LeetCode Sqrt(x)

69. Sqrt(x)

Implement int sqrt(int x).

Compute and return the square root of x, where x is guaranteed to be a non-negative integer.

Since the return type is an integer, the decimal digits are truncated and only the integer part of the result is returned.

Example 1:

Input: 4
Output: 2

Example 2:

Input: 8
Output: 2
Explanation: The square root of 8 is 2.82842..., and since 
             the decimal part is truncated, 2 is returned.

本题要对一个数开平方根。相当于LeetCode Valid Perfect Square的逆过程,很多方法都可以通用。 解法1。直接借用LeetCode Valid Perfect Square提到的牛顿法开方,代码如下:

class Solution {
public:
    int mySqrt(int x)
    {
        long long y = x;
        while (y * y > x) {
            y = (y + x / y) / 2;
        }
        return y;
    }
};

本代码提交AC,用时6MS。

解法2。二分搜索,由于sqrt(x)不可能超过x/2+1(查看两个函数图像),所以可以在[0,x/2+1]范围内二分搜索,因为是向下取整,所以返回的是r,代码如下:

class Solution {
public:
    int mySqrt(int x)
    {
        long long l = 0, r = x / 2 + 1;
        while (l <= r) {
            long long mid = (l + r) / 2;
            long long prod = mid * mid;
            if (prod == x)
                return mid;
            if (prod < x)
                l = mid + 1;
            else
                r = mid – 1;
        }
        return r;
    }
};

本代码提交AC,用时6MS。

三刷。暴力枚举:

class Solution {
public:
	int mySqrt(int x) {
		long long xx = x;
		if (x == 1)return 1;
		long long i = 1;
		for (; i < xx; ++i) {
			if (i*i > xx)break;
		}
		return i - 1;
	}
};

本代码提交AC,用时16MS,还是用前两个方法吧。

LeetCode Valid Perfect Square

LeetCode Valid Perfect Square Given a positive integer num, write a function which returns True if num is a perfect square else False. Note: Do not use any built-in library function such as sqrt. Example 1:

Input: 16
Returns: True
Example 2:
Input: 14
Returns: False

本题要判断一个数是否是完全平方数。有很多种解法,现列举如下: 解法1。牛顿法。牛顿法本是用来求解函数f(x)=0的根的,可以用来开方。$$f(x)=x^2-num$$等于0的正根就是num的根号。下面就是牛顿法求解f(x)=0的根的更新公式,$$x_{n+1}$$比$$x_n$$更接近f(x)=0的真实根。初始的时候可以随便代一个$$x_0$$到公式中。 对于函数$$f(x)=x^2-num$$,$$f'(x)=2x$$,所以牛顿递推式为$$!x_{n+1}=x_n-\frac{x_n^2-num}{2x_n}=(x_n+num/x_n)/2$$ 所以我们可以初始代入$$x_n=num$$,然后不断用牛顿法,直到x*x<=num时,如果x*x==num,则num为完全平方数,否则不是。 关于牛顿法用于开放的原理介绍,果壳网上有个人介绍得很详细。 代码如下: [cpp] class Solution { public: bool isPerfectSquare(int num) { long long x = num; while (x*x > num) { x = (x + num / x) / 2; } return x*x == num; } }; [/cpp] 本代码提交AC,用时0MS。 解法2。对于num,如果$$x=\frac{num}{2}$$的平方依然大于num,则$$x=\frac{x}{2}$$,如果x的平方依然大于num,则继续对x除以2,不断除,直到x平方小于等于num时,遍历[x,2*x]之间的数,看看x*x==num是否成立,如果成立,说明num是完全平方数,否则不是。这种解法在高级算法里好像讲过。完整代码如下: [cpp] class Solution { public: bool isPerfectSquare(int num) { if (num == 1)return true; long long x = num >> 1; while (x*x > num)x >>= 1; for (int y = x; y <= (x << 1); ++y) { if (y*y == num)return true; } return false; } }; [/cpp] 本代码提交AC,用时3MS。 解法3。观测下面的等式发现完全平方数都是由连续奇数相加而来,所以我们也可以把连续奇数加起来,直到超过num时,看看和与num是否相等。 1 = 1 4 = 1 + 3 9 = 1 + 3 + 5 16 = 1 + 3 + 5 + 7 25 = 1 + 3 + 5 + 7 + 9 36 = 1 + 3 + 5 + 7 + 9 + 11 …. 1+3+…+(2n-1) = (2n-1 + 1)n/2 = n*n 代码如下: [cpp] class Solution { public: bool isPerfectSquare(int num) { long long sum = 1; for (int i = 3; sum < num; i += 2) sum += i; return sum == num; } }; [/cpp] 本代码提交AC,用时3MS。 解法4。二分搜索。l=0,r=num,mid=(l+r)/2,根据mid*mid和num的大小关系一步步缩小范围。复杂度为O(lgn),完整代码如下: [cpp] class Solution { public: bool isPerfectSquare(int num) { long long l = 0, r = num; while (l <= r) { long long mid = (l + r) / 2; long long prod = mid*mid; if (prod == num)return true; if (prod < num)l = mid + 1; else r = mid – 1; } return l*l == num; } }; [/cpp] 本代码提交AC,用时0MS。 注意这个题的代码中,为了防止int越界,都需要用long long。 参考: http://bookshadow.com/weblog/2016/06/26/leetcode-valid-perfect-square/ http://www.cnblogs.com/grandyang/p/5619296.html]]>

LeetCode Increasing Triplet Subsequence

334. Increasing Triplet Subsequence334. Increasing Triplet Subsequence

Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the array.

Formally the function should:

Return true if there exists i, j, k
such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false.

Note: Your algorithm should run in O(n) time complexity and O(1) space complexity.

Example 1:

Input: [1,2,3,4,5]
Output: true

Example 2:

Input: [5,4,3,2,1] Output: false

问一个数组中是否有严格递增的三个数存在。
解法:令a是当前最小值,b是比a大的最小值,如果某个nums[i]>b,则a,b,nums[i]构成严格递增的三个数。
因为a,b是最小的递增二元组,如果连这样都没找到递增序列,则不可能有递增三元组了。
完整代码如下,需要注意数组中可能有相同元素,所以第一个if要用<=。

class Solution {
public:
    bool increasingTriplet(vector<int>& nums)
    {
        int a = INT_MAX, b = INT_MAX;
        for (int i = 0; i < nums.size(); ++i) {
            if (nums[i] <= a) {
                // 必须<=
                a = nums[i];
            }
            else if (nums[i] < b) { // <或<=
                b = nums[i];
            }
            if (nums[i] > b) // 必须>
                return true;
        }
        return false;
    }
};

本代码提交AC,用时9MS。
二刷。首先想到了最长上升子序列,求到LIS,如果长度大于等于3的话,则肯定存在上升的3元组。代码如下:

class Solution {
private:
    int lengthOfLIS(vector<int>& nums)
    {
        int n = nums.size();
        if (n < 1)
            return 0;
        vector<int> B = { nums[0] };
        for (int i = 1; i < n; ++i) {
            if (nums[i] > B.back())
                B.push_back(nums[i]);
            else {
                *lower_bound(B.begin(), B.end(), nums[i]) = nums[i];
            }
        }
        return B.size();
    }
public:
    bool increasingTriplet(vector<int>& nums) { return lengthOfLIS(nums) >= 3; }
};

本代码提交AC,用时6MS。

LeetCode Unique Binary Search Trees

Given n, how many structurally unique BST’s (binary search trees) that store values 1 … n?

Example:

Input: 3
Output: 5
Explanation:
Given n = 3, there are a total of 5 unique BST's:

   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3

给定n,问保存1~n的二叉搜索树共有多少种形式。注意要充分利用二叉搜索树的特点,左孩子小于等于根节点,根节点小于等于右孩子。如果trees[0,…,n-1]保存了0,…,n-1个节点的二叉搜索树的个数,现在要求trees[n]。n个节点,除了根节点,剩余n-1个节点,根据选取的根节点的不同,把n-1个节点分在了不同的左右子树中,以该节点为根的有效的二叉搜索树个数等于左右孩子有效的二叉搜索树个数乘积。
以3个点为例,如下图所示,如果选取1作为根节点,则左右孩子的节点数分别为0,2,所以可以有的二叉搜索树形式为trees[0]*trees[2];如果选取2作为根节点,则左右孩子的节点数分别为1,1,所以可以有的二叉搜索树形式为trees[1]*trees[1];同理3为trees[2]*trees[0]。

 1        1           2            3       3
   \       \       /     \        /       /
    3       2     1       3      2       1
   /         \                  /         \
 2            3                1           2

所以trees[n]=trees[0]*trees[n-1]+trees[1]*trees[n-2]+…+trees[n-1]*trees[1]。这其实就是卡特兰数

完整代码如下:

class Solution {
public:
    int numTrees(int n)
    {
        if (n <= 1)
            return 1;
        vector<int> trees(n + 1);
        trees[0] = 1;
        trees[1] = 1;
        for (int i = 2; i <= n; ++i) {
            for (int j = 0; j < i; ++j) {
                trees[i] += trees[j] * trees[i – j – 1];
            }
        }
        return trees[n];
    }
};

本代码提交AC,用时0MS。

LeetCode Elimination Game

LeetCode Elimination Game There is a list of sorted integers from 1 to n. Starting from left to right, remove the first number and every other number afterward until you reach the end of the list. Repeat the previous step again, but this time from right to left, remove the right most number and every other number from the remaining numbers. We keep repeating the steps again, alternating left to right and right to left, until a single number remains. Find the last number that remains starting with a list of length n. Example:

Input:
n = 9,
1 2 3 4 5 6 7 8 9
2 4 6 8
2 6
6
Output:
6

本题介绍了一个消除游戏,就是1~n排列了n个数,先从左往右每隔一个数消除一个(包含1),然后从右往左每隔一个数消除一个(包含最后一个数),如此循环,直到只剩一个数,要求输出这个数。 我一开始以为这是个模拟题,直接用STL的双向链表list模拟了,代码如下: [cpp] class Solution { public: int lastRemaining(int n) { list<int> l; for (int i = 1; i <= n; i++)l.push_back(i); while (l.size() != 1) { list<int>::iterator it = l.begin(); while (it != l.end()) { it = l.erase(it); if (it != l.end())++it; } if (l.size() == 1)break; list<int>::reverse_iterator rit = l.rbegin(); while (rit != l.rend()) { rit = list<int>::reverse_iterator(l.erase(–(rit.base()))); if (rit != l.rend())++rit; } if (l.size() == 1)break; } return *l.begin(); } }; [/cpp] 很不幸,本代码提交TLE,超时了。 网上查题解,这个人讲得比较清楚。一开始1,2,3,4,5,6,7,8,…,n,第一次从左往右消除之后,剩余2,4,6,8…,n,其实就相当于2*(1,2,3,4,…n/2)。但是这个时候我们要对1,2,3,4,…n/2从右往左消除了,那么从右往左和从左往右消除得到的结果有什么规律呢,他们的结果应该是呈镜像对称的,也就是说如果长度为n/2的话,如果从左往右的结果为x,那么从右往左的结果就应该是n/2+1-x;同理如果从右往左的结果是y的话,那么从左往右的结果就应该是n/2+1-y。 代码实现为: [cpp] class Solution { public: int lastRemaining(int n) { return n == 1 ? 1 : 2 * (n / 2 + 1 – lastRemaining(n / 2)); } }; [/cpp] 本代码提交AC,用时49MS。]]>

LeetCode Linked List Random Node

LeetCode Linked List Random Node Given a singly linked list, return a random node’s value from the linked list. Each node must have the same probability of being chosen. Follow up: What if the linked list is extremely large and its length is unknown to you? Could you solve this efficiently without using extra space? Example:

// Init a singly linked list [1,2,3].
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
Solution solution = new Solution(head);
// getRandom() should return either 1, 2, or 3 randomly. Each element should have equal probability of returning.
solution.getRandom();

本题要从一个链表中随机取一个数。常规解法是先遍历一遍链表,得到链表长度n,然后rand()%n确定随机取的节点位置,最后遍历链表找到第rand()%n个数。 但是这种解法肯定不是大家想要的,Follow up里提到,如果链表很长,没法提前知道链表长度,该怎么办呢?查阅题解才发现需要用到一个叫做水塘抽样的方法,这篇博客介绍得挺详细的。简单来说,就是假设有n个节点(n提前不知道),我们希望每个节点被采样的概率都是1/n,我们可以这样做,遍历到第i个节点时,以概率1/i采样i号节点。我们来算一算第i号节点被采样的概率=遍历到第i号节点时,要被采样,且后面节点都不被采样,公式为: $$!\frac{1}{i}*\frac{i}{i+1}*\frac{i+1}{i+2}*…*\frac{n-1}{n}=\frac{1}{n}$$ 即每个节点被采样到的概率都等于$$\frac{1}{n}$$。 具体怎样实现以$$\frac{1}{i}$$采样呢,我们可以令k=rand()%i,则k随机分布在[0,i-1],所以k==0的概率就是$$\frac{1}{i}$$。完整代码如下: [cpp] class Solution { private: ListNode* mhead; public: /** @param head The linked list’s head. Note that the head is guaranteed to be not null, so it contains at least one node. */ Solution(ListNode* head) { mhead = head; } /** Returns a random node’s value. */ int getRandom() { int ans = mhead->val, n = 2; ListNode* cur = mhead->next; while (cur) { int r = rand() % n; if (r == 0)ans = cur->val; cur = cur->next; ++n; } return ans; } }; [/cpp] 本代码提交AC,用时49MS。]]>

LeetCode Reconstruct Original Digits from English

LeetCode Reconstruct Original Digits from English Given a non-empty string containing an out-of-order English representation of digits 0-9, output the digits in ascending order. Note:

  1. Input contains only lowercase English letters.
  2. Input is guaranteed to be valid and can be transformed to its original digits. That means invalid inputs such as “abc” or “zerone” are not permitted.
  3. Input length is less than 50,000.
Example 1:
Input: "owoztneoer"
Output: "012"
Example 2:
Input: "fviefuro"
Output: "45"

给定一个用英文单词表示数字的字符串,要求恢复出这个数字字符串,英文字符串是被打乱了的。 这题纯粹是个找规律的题,先写出10个数字的英文单词,然后找找那个字符是每个单词特有的字符,比如可以确定的有:
  • 0:z
  • 2:w
  • 4:u
  • 6:x
  • 8:g
找完上述5个单词之后,剩下的5个单词中每个单词特有的字符为:
  • 1:o
  • 3:t
  • 5:f
  • 7:s
  • 9:i
所以我们首先找到字符和频率的对应关系,然后根据上面的顺序依次减掉相应单词的频率,并把数字放到结果数组中,最后从结果数组中构建结果字符串。完整代码如下: [cpp] class Solution { public: string originalDigits(string s) { vector<int> hash(26, 0); vector<int> digits(10, 0); for (int i = 0; i < s.size(); ++i) { ++hash[s[i] – ‘a’]; } while (hash[‘z’ – ‘a’]) { // 0 ++digits[0]; –hash[‘z’ – ‘a’]; –hash[‘e’ – ‘a’]; –hash[‘r’ – ‘a’]; –hash[‘o’ – ‘a’]; } while (hash[‘w’ – ‘a’]) { // 2 ++digits[2]; –hash[‘t’ – ‘a’]; –hash[‘w’ – ‘a’]; –hash[‘o’ – ‘a’]; } while (hash[‘u’ – ‘a’]) { // 4 ++digits[4]; –hash[‘f’ – ‘a’]; –hash[‘o’ – ‘a’]; –hash[‘u’ – ‘a’]; –hash[‘r’ – ‘a’]; } while (hash[‘x’ – ‘a’]) { // 6 ++digits[6]; –hash[‘s’ – ‘a’]; –hash[‘i’ – ‘a’]; –hash[‘x’ – ‘a’]; } while (hash[‘g’ – ‘a’]) { // 8 ++digits[8]; –hash[‘e’ – ‘a’]; –hash[‘i’ – ‘a’]; –hash[‘g’ – ‘a’]; –hash[‘h’ – ‘a’]; –hash[‘t’ – ‘a’]; } while (hash[‘o’ – ‘a’]) { // 1 ++digits[1]; –hash[‘o’ – ‘a’]; –hash[‘n’ – ‘a’]; –hash[‘e’ – ‘a’]; } while (hash[‘t’ – ‘a’]) { // 3 ++digits[3]; –hash[‘t’ – ‘a’]; –hash[‘h’ – ‘a’]; –hash[‘r’ – ‘a’]; –hash[‘e’ – ‘a’]; –hash[‘e’ – ‘a’]; } while (hash[‘f’ – ‘a’]) { // 5 ++digits[5]; –hash[‘f’ – ‘a’]; –hash[‘i’ – ‘a’]; –hash[‘v’ – ‘a’]; –hash[‘e’ – ‘a’]; } while (hash[‘s’ – ‘a’]) { // 7 ++digits[7]; –hash[‘s’ – ‘a’]; –hash[‘e’ – ‘a’]; –hash[‘v’ – ‘a’]; –hash[‘e’ – ‘a’]; –hash[‘n’ – ‘a’]; } while (hash[‘i’ – ‘a’]) { // 9 ++digits[9]; –hash[‘n’ – ‘a’]; –hash[‘i’ – ‘a’]; –hash[‘n’ – ‘a’]; –hash[‘e’ – ‘a’]; } string ans = ""; for (int i = 0; i < 10; i++) { ans += string(digits[i], ‘0’ + i); } return ans; } }; [/cpp] 本代码提交AC,用时26MS。]]>

LeetCode Intersection of Two Arrays II

LeetCode Intersection of Two Arrays II Given two arrays, write a function to compute their intersection. Example: Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2, 2]. Note:

  • Each element in the result should appear as many times as it shows in both arrays.
  • The result can be in any order.
Follow up:
  • What if the given array is already sorted? How would you optimize your algorithm?
  • What if nums1‘s size is small compared to nums2‘s size? Which algorithm is better?
  • What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once?

求两个数组的交集,这里的交集又不同之前LeetCode Intersection of Two Arrays的交集了,这里的交集不再满足集合的互异性,两个数组中有多个同一个数,有几个共有,交集里就有几个,看例子就知道了。 这其实简化了问题,我们对其中一个数组hash,建立数字和频率的hash表,然后遍历另一个数组,hash表中有,则加入交集,同时hash中的频率减1,也不需要对结果去重了。完整代码如下: [cpp] class Solution { public: vector<int> intersect(vector<int>& nums1, vector<int>& nums2) { unordered_map<int, int> hash; vector<int> ans; for (int i = 0; i < nums1.size(); ++i) { ++hash[nums1[i]]; } for (int i = 0; i < nums2.size(); ++i) { if (hash[nums2[i]]>0) { ans.push_back(nums2[i]); –hash[nums2[i]]; } } return ans; } }; [/cpp] 本代码提交AC,用时6MS。 回答一下Follow up的三个问题: 如果数组已排序,则可以用归并排序的思路求交集,两个指针i,j分别指向两个数组,然后判断nums[i]==nums[j],如果相等,则加入交集,i,j都往后移;否则根据大小关系选择后移i或j。 不过我觉得代码中的Hash思路已经够快了,时间复杂度应该都是O(n1+n2),只不过Hash毕竟需要计算Hash值,Hash占用的隐性空间也比较大,所以归并的思路可能会快一些。 如果nums1.size<nums2.size(),则归并的思路会快一些,因为归并的话,其实复杂度是O(min(n1,n2)),当一个数组的指针走到头之后,算法就结束了,而Hash的话,就必须走完两个数组。 如果nums2不能一次load进内存,则分批load内存查Hash。]]>

LeetCode Binary Watch

LeetCode Binary Watch A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the bottom represent the minutes (0-59). Each LED represents a zero or one, with the least significant bit on the right. For example, the above binary watch reads “3:25”. Given a non-negative integer n which represents the number of LEDs that are currently on, return all possible times the watch could represent. Example:

Input: n = 1
Return: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"]
Note:
  • The order of output does not matter.
  • The hour must not contain a leading zero, for example “01:00” is not valid, it should be “1:00”.
  • The minute must be consist of two digits and may contain a leading zero, for example “10:2” is not valid, it should be “10:02”.

程序员有一个二进制的手表,如图所示,上面4个灯表示小时,下面6个灯表示分钟。现在告诉你手表上亮着n盏灯,问共有多少种时间的可能,要求输出所有可能的时间。 我觉得这应该算中等题,稍微有一点麻烦。 首先我们要把亮着的n盏灯分到小时和分钟上,比如小时亮x盏灯,分钟亮y盏灯,x+y=n。对于小时,长度为4bit,要把亮着的x盏灯填入这4bit中,共有$$C_4^x$$种填法,可以用递归的思路实现。对于分钟,长度为6bit,要把亮着的y盏灯填入这6bit中,共有$$C_6^y$$种填法,也可以用递归的思路实现。 所以我们可以统一小时和分钟的递归算法,具体看代码comb函数。假设初始的灯的状态为cur,我们就是要在cur的[s,t) bit之间填入ones个1bit,对于小时,长度为4bit,所以传入cur=0, s=0, t=4;对于分钟,长度为6bit,所以传入cur=0, s=0, t=6。注意每次递归调用的时候,s都要更新,否则生成的组合结果会有重复。 生成了小时和分钟的组合之后,我们再把小时和分钟字符串组合起来,这个就简单了,不再赘述。完整代码如下: [cpp] class Solution { public: // cur为传入的二进制串,comb要把ones个1填入[s,t)中 void comb(vector<int>& res, int cur, int s, int t, int ones) { if (ones == 0)res.push_back(cur); else { for (int i = s; i < t; ++i) { if ((cur&(1 << i)) == 0) { comb(res, cur | (1 << i), i + 1, t, ones – 1); // 递归把ones-1个1填入[i+1,t)中 } } } } vector<string> readBinaryWatch(int num) { vector<string> ans; for (int hour = 0; hour <= 3; ++hour) { if (hour > num)break; vector<int> hours; comb(hours, 0, 0, 4, hour); vector<int> minutes; comb(minutes, 0, 0, 6, num – hour); for (int i = 0; i < hours.size(); ++i) { if (hours[i] > 11)continue; string tmp_h = to_string(hours[i]); for (int j = 0; j < minutes.size(); ++j) { if (minutes[j] > 59)continue; string tmp_m = to_string(minutes[j]); if (tmp_m.size() < 2)tmp_m = "0" + tmp_m; ans.push_back(tmp_h + ":" + tmp_m); } } } return ans; } }; [/cpp] 本代码提交AC,用时0MS。]]>

LeetCode Shuffle an Array

LeetCode Shuffle an Array Shuffle a set of numbers without duplicates. Example:

// Init an array with set 1, 2, and 3.
int[] nums = {1,2,3};
Solution solution = new Solution(nums);
// Shuffle the array [1,2,3] and return its result. Any permutation of [1,2,3] must equally likely to be returned.
solution.shuffle();
// Resets the array back to its original configuration [1,2,3].
solution.reset();
// Returns the random shuffling of array [1,2,3].
solution.shuffle();

本题要对一个数组随机洗牌,也就是随机打乱。 第一种思路是,相当于对原数组进行无放回的随机抽样,每次从原数组中随机抽取一个数字,放到新数组中,然后在剩余数组中再随机抽样,直到抽完所有数字。 具体实现是这样的,我们先令ans=original,此时我们要从n个数中随机抽样,把随机抽到的数字放到ans的末尾;然后随机抽样的整体减1,也就是n–,从n-1个数中再随机抽样,放到ans的倒数第二个位置。所以我们令pos为随机抽到的数应该放的位置,那么此时的抽样整体长度就是pos+1,每次把抽到的数和pos处的数交换一下。 完整代码如下,注意不能自己设置随机种子,要不然会WA! [cpp] class Solution { private: vector<int> original; public: Solution(vector<int> nums) { original = nums; } /** Resets the array to its original configuration and return it. */ vector<int> reset() { return original; } /** Returns a random shuffling of the array. */ vector<int> shuffle() { //srand(time(NULL)); // caution!! vector<int> ans = original; int pos = ans.size() – 1; while (pos > 0) { int r = rand() % (pos + 1); swap(ans[pos], ans[r]); –pos; } return ans; } }; [/cpp] 本代码提交AC,用时275MS。 还有一种思路更简单,遍历数组,对于每一位,都随机生成一个需要交换的位置,然后交换。完整代码如下: [cpp] class Solution { private: vector<int> original; public: Solution(vector<int> nums) { original = nums; } /** Resets the array to its original configuration and return it. */ vector<int> reset() { return original; } /** Returns a random shuffling of the array. */ vector<int> shuffle() { //srand(time(NULL)); // caution!! vector<int> ans = original; for (int i = 0; i < ans.size(); ++i) { int j = rand() % ans.size(); swap(ans[i], ans[j]); } return ans; } }; [/cpp] 本代码提交AC,用时269MS。]]>