주제: 136. 한 번만 나타나는 숫자
시간 선형 복잡도와 공간 상수 복잡도가 필요합니다.
솔루션: 비트별 XOR
XOR의 속성에 관하여: 1. 0이 있는 XOR은 자기 자신과 같습니다. 2. 자기 자신이 있는 XOR은 0과 같습니다. 3. XOR 연산에는 교환법칙과 결합법칙이 있습니다.
class Solution {
public:
int singleNumber(vector<int>& nums) {
int t=0;
for(int num:nums) t = t^num; //(a⊕a)⊕(a⊕a)⊕⋯⊕(a⊕a)⊕t
return t;
}
};
주제: 169. 주요 요소
내 해결책: (잘못됨)
벡터가 초기화되지 않아 복잡도가 매우 높습니다. 벡터를 사용할 때와 맵을 사용할 때의 차이점에 주의하세요. 맵은 크기를 초기화할 필요가 없습니다.
class Solution {
public:
int majorityElement(vector<int>& nums) {
int n = nums.size(),ans;
vector<int> counts;
for(int num:nums){
counts[num]++;
}
for(int i=0; i<counts.size(); ++i){
if(counts[i]>n/2){
ans = i;
break;
}
}
return ans;
}
};
다른 해결 방법 1: 해시 테이블
class Solution {
public:
int majorityElement(vector<int>& nums) {
int ans, cnt=0;
unordered_map<int, int> hash; //使用hash表存储每个数字出现的次数,取出次数最多的数字
for(int num:nums){
++hash[num];
if(hash[num]>cnt){
//在循环中直接记录最大值
ans = num;
cnt = hash[num];
}
}
return ans;
}
};
다른 해결 방법 2: 정렬
정렬 후 모드는 n/2 위치에 나타납니다.
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(), nums.end()); //注意sort的写法,头和尾
return nums[nums.size()/2];
}
};
다른 해결책 3: "산 정상을 점령하라"
후보 모드 후보와 그것이 나타나는 횟수를 cnt(초기 0)로 설정하고,
모드를 +1로, 다른 숫자를 -1로 기록하고 모두 더하면 그 합이 0보다 크다는 것은 자명하다. 결과 자체를 보면 다른 수치보다 모드가 더 많다는 것을 알 수 있습니다.
class Solution {
public:
int majorityElement(vector<int>& nums) {
int candidate, cnt=0;
for(int num:nums){
if(cnt==0){
//如果目前没有候选者,当前元素成为候选者
candidate=num;
}
if(candidate==num){
//是候选者,数量++
++cnt;
}else{
//不是候选者,数量--,直到等于0,设立新的候选者,众数数量最多,最后一定会是候选者
--cnt;
}
}
return candidate;
}
};
주제 : 15. 세 숫자의 합
해결책: 정렬 ➕ 이중 포인터
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
if(n<3) return {
}; //特判,元素个数小于3,返回空数组
sort(nums.begin(), nums.end()); //排序
vector<vector<int>> ans; //存储答案
for(int i=0; i<n; ++i){
//从头遍历
if(nums[i]>0) return ans; //如果目前元素为最小元素都大于0,则不可能存在这之后有三个元素加和等于0
if(i>0 && nums[i]==nums[i-1]) continue; //元素不能重复
int k = -nums[i]; //求两数之和等于-nums[i]
int t = n-1; //尾指针
int h = i+1; //头指针
while(h<t){
//外条件:头小于尾
if(nums[h]+nums[t]>k){
//如果两数之和大于k,则尾指针前移
--t;
}else if(nums[h]+nums[t]==k){
//若等于k,则存储这三个数,同时移动头尾指针
ans.push_back({
nums[i], nums[h], nums[t]});
--t; ++h;
while(h<t && nums[h]==nums[h-1]) ++h; //头指针不重复
while(h<t && nums[t]==nums[t+1]) --t; //尾指针不重复
}else{
//若小于k,头指针后移
++h;
}
}
}
return ans; //返回答案
}
};