【本文持续更新】
78. 子集
题目: 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
本题做过好几遍了, 之前用的是回溯法, 本次使用的是位操作的思想。
位操作解法: 将 \(nums\) 的每一个位置看作一个 \(bit\),如果某个 \(bit\) 为1,表示 \(nums[i]\) 需要加入子集,否则不加入。显然, 每个子集都对应一个比特串, 比特串从 \(0...0\) 到 \(1...1\) 变化(也就从另外一个角度证明了子集的数目为 \(2^n\) )。
下面举例说明, 当 $ nums = [1,2] $ 时:
比特位 | 对应子集 |
---|---|
0 0 | [ ] |
0 1 | [2] |
1 0 | [1] |
1 1 | [1,2] |
位操作代码(C++):
class Solution
{
public:
vector<vector<int>> subsets(vector<int> &nums)
{
vector<vector<int>> vv;
int total = 1 << nums.size();
for (int i = 0; i < total; i++)
{
vv.push_back(getItem(i, nums));
}
return vv;
}
vector<int> getItem(int n, const vector<int> &nums)
{
vector<int> v;
for (int i = 0; i < nums.size(); i++)
{
if ((n >> i) & 0x1)
v.push_back(nums[i]);
}
return v;
}
};
回溯法代码(python):
class Solution:
def __init__(self):
self.ans = list()
self.ans.append([])
def subsets(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
cur = []
self.helper(cur, nums)
return self.ans
def helper(self, cur: list, nums: list):
for i in range(0, len(nums)):
cur.append(nums[i])
self.ans.append(list(cur))
self.helper(cur, nums[(i + 1):])
cur.pop()
136. 只出现一次的数字
题目:给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
示例:
输入: [2,2,1]
输出: 1
输入: [4,1,2,1,2]
输出: 4
解题前,首先需要熟知 3 个结论:
- \(0 \oplus x = x\)
- \(x \oplus x = 0\)
- \((x \oplus y) \oplus z = x \oplus (y \oplus z)\)
这是异或的 3 个性质。回到本题,要求找出只出现 1 (或者说奇数次,本题方法依旧适用)。显然,只要某个 \(k\) 出现偶数次,所有的 \(k\) 异或结果是 0。对于出现奇数次的数字 \(x\),所有的 \(x\) 异或的结果是 \(x\)。
只要理解了上面 3 个结论, 直接看代码:
class Solution {
public:
int singleNumber(vector<int>& nums) {
int x = 0;
for (auto k:nums)
{
x^=k;
}
return x;
}
};