【思维题】B023_LC_二倍数对数组(暴力统计 / 逻辑优化)

一、Problem

给定一个长度为偶数的整数数组 A,只有对 A 进行重组后可以满足 “对于每个 0 <= i < len(A) / 2,都有 A[2 * i + 1] = 2 * A[2 * i]” 时,返回 true;否则,返回 false。

输入:[4,-2,2,-4]
输出:true
解释:我们可以用 [-2,-4] 和 [2,4] 这两组组成 [-2,-4,2,4] 或是 [2,4,-2,-4]

提示:

0 <= A.length <= 30000
A.length 为偶数
-100000 <= A[i] <= 100000

二、Solution

方法一:map

最暴力的方法就是用计数器 cnt 记录配对数, x x x 如果能找到一个 2 x 2x 2x,那么计数器 + 2 +2 +2,最后能均匀切分完成的充要条件是: c n t = n cnt = n cnt=n

class Solution {
public:
    bool canReorderDoubled(vector<int>& A) {
    	int n = A.size(), cnt = 0;
    	unordered_map<int, int> m;
    	sort(A.begin(), A.end());
    	for (int x : A) m[x]++;

    	for (int x : A) if (m[x] && m[2*x]) {
    		cnt += 2;
    		m[x]--, m[2*x]--;
    	}
    	return cnt == n;
    }
};

优化一下:当 x 为负数时,应该找它的 x/2 是否存在;当 x x x 为正数时,应该找它的 2 x 2x 2x 是否存在,有了这两个条件,就可以做出终止判断地终止循环,而不用一直遍历下去

class Solution {
public:
    bool canReorderDoubled(vector<int>& A) {
    	int n = A.size();
    	unordered_map<int, int> m;
    	sort(A.begin(), A.end());
    	for (int x : A) m[x]++;

    	for (int x : A) {
            int c = m[x];
    		if (x < 0 && c > 0) {
    			if (m[x/2] < c) 
    				return false;
    			m[x/2] -= c;
    		} else if (x > 0 && c > 0) {
    			if (m[2*x] < c)
    				return false;
    			m[2*x] -= c;
    		}
            m[x] -= c;
    	}
    	return true;
    }
};

嗯不错,RT 减少了不少…
复杂度分析

  • 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
  • 空间复杂度: O ( n ) O(n) O(n)

你可能感兴趣的:(#,思维题)