文章目录
- 342. 4的幂
- 1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?
- 523. 连续的子数组和
- 525. 连续数组
- 160. 相交链表
- 203. 移除链表元素
- [474. 一和零](https://leetcode-cn.com/problems/ones-and-zeroes/)
- [797. 所有可能的路径](https://leetcode-cn.com/problems/all-paths-from-source-to-target/)
- [494. 目标和](https://leetcode-cn.com/problems/target-sum/)
- [1049. 最后一块石头的重量 II](https://leetcode-cn.com/problems/last-stone-weight-ii/)
- [879. 盈利计划](https://leetcode-cn.com/problems/profitable-schemes/)
- [70. 爬楼梯](https://leetcode-cn.com/problems/climbing-stairs/)
- [518. 零钱兑换 II](https://leetcode-cn.com/problems/coin-change-2/)
- [279. 完全平方数](https://leetcode-cn.com/problems/perfect-squares/)
- [278. 第一个错误的版本](https://leetcode-cn.com/problems/first-bad-version/)
- [374. 猜数字大小](https://leetcode-cn.com/problems/guess-number-higher-or-lower/)
- [852. 山脉数组的峰顶索引](https://leetcode-cn.com/problems/peak-index-in-a-mountain-array/)
- [877. 石子游戏](https://leetcode-cn.com/problems/stone-game/)
- [65. 有效数字](https://leetcode-cn.com/problems/valid-number/)
- [1239. 串联字符串的最大长度](https://leetcode-cn.com/problems/maximum-length-of-a-concatenated-string-with-unique-characters/) 位运算
- [1600. 皇位继承顺序](https://leetcode-cn.com/problems/throne-inheritance/)
- [401. 二进制手表](https://leetcode-cn.com/problems/binary-watch/)
- [剑指 Offer 38. 字符串的排列](https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/)
- [剑指 Offer 15. 二进制中1的个数](https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de-ge-shu-lcof/)
- [149. 直线上最多的点数](https://leetcode-cn.com/problems/max-points-on-a-line/)
- [752. 打开转盘锁](https://leetcode-cn.com/problems/open-the-lock/)(BFS)
- [773. 滑动谜题](https://leetcode-cn.com/problems/sliding-puzzle/)(BFS)
- [5797. 两个数对之间的最大乘积差](https://leetcode-cn.com/problems/maximum-product-difference-between-two-pairs/)(sort)
- [815. 公交路线](https://leetcode-cn.com/problems/bus-routes/)
- [168. Excel表列名称](https://leetcode-cn.com/problems/excel-sheet-column-title/)
- [剑指 Offer 37. 序列化二叉树](https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/)
- [LCP 07. 传递信息](https://leetcode-cn.com/problems/chuan-di-xin-xi/) (邻接矩阵)
- [451. 根据字符出现频率排序](https://leetcode-cn.com/problems/sort-characters-by-frequency/)(pair 排序)
- [645. 错误的集合](https://leetcode-cn.com/problems/set-mismatch/)
- [1418. 点菜展示表](https://leetcode-cn.com/problems/display-table-of-food-orders-in-a-restaurant/)
- [1711. 大餐计数](https://leetcode-cn.com/problems/count-good-meals/)
- [面试题 17.10. 主要元素](https://leetcode-cn.com/problems/find-majority-element-lcci/)
- [H 指数 II](https://leetcode-cn.com/problems/h-index-ii/)
342. 4的幂
#include <cmath>
#include<algorithm>
class Solution {
public:
bool isPowerOfFour(int n) {
// log(4^n) = n *log(4)
long x = 1;
while(x<n){
x = x<<2;
}
return x==n;
}
};
// 100000000
// 4 16 64 256
// 100
// 011
// 10000
// 1000000
// 4
// n&&(n-1)==0
1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?
tips: 前缀法
计算2个区间,第一个是截止到favoriteDay的时候,一共最快或者最慢吃的糖果数量[x1, y1]。
第二个区间是截止到favoriteDay的时候,想吃的糖果type编号的范围[x2, y2]。
如果第一个区间中有想吃糖果type的编号,也就是2个区间有交集,那么为True。
// 构造 sum[i] = sum[i - 1] + candiesCount[i]
class Solution {
public:
vector<bool> canEat(vector<int>& candiesCount, vector<vector<int>>& queries) {
int l1 = candiesCount.size();
int l2 = queries.size();
vector<long long> sum(l1);
sum[0] = candiesCount[0];
for(int i = 1; i < l1; i++){
sum[i] = sum[i - 1] + candiesCount[i];
}
vector<bool> ans;
for(int i = 0; i < l2; i++){
int type = queries[i][0];
int day = queries[i][1];
int capi = queries[i][2];
// [x1, y1]
// slowest
long long x1 = day+1;
// fastest
long long y1 =(day + 1) * (long long)capi;
// [x2, y2]
long long x2 = (type < 1 ? 1 : sum[type - 1] + 1);
long long y2 = sum[type];
ans.push_back(!(x1>y2||y1<x2));
}
return ans;
}
};
523. 连续的子数组和
前缀法 + 同余定理 + 无序表;
不能暴力解,会超时;
考虑到同余定理以及减少复杂度,就要用到统计出现相同余数的nums的index。用到map中的count方法。
//当 prefixSums}[q]-prefixSums[p] 为 k的倍数时,prefixSums}[p]和 prefixSums[q] 除以 k 的余数相同
//
class Solution {
public:
bool checkSubarraySum(vector<int>& nums, int k) {
int m = nums.size();
// 满足第一个条件。
if (m < 2) {
return false;
}
// 前缀法
vector<int> sum(m);
sum[0] = nums[0];
for(int i = 1; i < m; i++){
sum[i] = sum[i-1] + nums[i];
}
// 默认int int的无序表中的元素值为0
unordered_map<int, int> map;
map[0] = -1;
for(int i = 0; i < m; i++){
int s = sum[i] % k;
// 如果找到 计算len
if(map.count(s)){
int len = i - map[s];
if(len >=2)
return true;
}
// 没有找到,存入余数为s时的最先的index的位置。
else{
map[s] = i;
}
}
return false;
}
};
525. 连续数组
给定一个二进制数组 nums
, 找到含有相同数量的 0
和 1
的最长连续子数组,并返回该子数组的长度。
输入: nums = [0,1]
输出: 2
说明: [0, 1] 是具有相同数量0和1的最长连续子数组。
输入: nums = [0,1,0]
输出: 2
说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。
class Solution {
public:
int findMaxLength(vector<int>& nums) {
int m = nums.size();
vector<int> sum(m);
vector<int> cons(m);
unordered_map<int, int> map;
for(int i = 0; i < m; i++){
if(nums[i] == 1)
cons[i] = 1;
else
cons[i] = -1;
}
sum[0] = cons[0];
for(int i = 1; i < m; i++){
sum[i] = sum[i - 1] + cons[i];
}
map[0] = -1;
// cout<< map[-1];
int maxlength = 0;
int cnt = 0;
for(int i = 0; i < m; i++){
if(map.count(sum[i])){ // map.count(-1)
int index = map[sum[i]];
maxlength = max(maxlength, i - index);
}else{
map[sum[i]] = i;
}
}
return maxlength;
}
};
160. 相交链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if( headA == NULL || headB == NULL)
return NULL;
ListNode *headb_head;
headb_head = headB;
while(headA != NULL){
while(headB != NULL){
if(headB == headA){
return headB;
}
headB = headB->next;
}
headA = headA->next;
headB = headb_head;
}
return NULL;
// 哈希集合方法
/*
unordered_set<ListNode*> set;
ListNode* temp;
temp = headA;
while(temp != NULL){
set.insert(temp);
temp = temp->next;
}
temp = headB;
while(temp != NULL){
if(set.count(temp))
return temp;
temp = temp->next;
}
return NULL;
*/
}
/* 双指针
if(headA == NULL || headB == NULL)
return NULL;
ListNode *pa = headA, *pb = headB;
while(pa != pb){
if(pa == NULL){
pa = headB;
}else{
pa = pa->next;
}
if(pb == NULL){
pb = headA;
}else{
pb = pb->next;
}
}
return pa;
*/
};
203. 移除链表元素
因为有可能链表头所在的元素就是等于val,需要移除,因此考虑temp->next = temp->next->next;
以及temp->next->val != val
的时候,就有一个缺漏,头结点没有考虑。这题的关键在于构造一个哑结点dummyNode
,dummyNode = head->next
,其次在最后返回的时候,temp已经修改了链表连接的元素,需要return dummyNode->next
其中哑结点的构造有ListNode以及ListNode*两种类型,问了师兄以后,应该这么写:
ListNode p = ListNode(0);
ListNdoe *p = new ListNode(0); // 必须要有new 不然无法构建指针变量
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
if(head == nullptr)
return nullptr;
ListNode* dummyNode = new ListNode(0);
dummyNode->next = head;
ListNode* temp = dummyNode;
while(temp->next != nullptr){
if(temp->next->val != val){
temp = temp->next;
}else{
temp->next = temp->next->next;
}
}
return dummyNode->next;
/*
// 递归 其实就是之前想的从前往后,但是当时没法确定如果当前元素等于val,那前一个元素怎么获得的问题,但是反思了一下这个就是递归。
if(head == nullptr)
return head;
head->next = removeElements(head->next, val);
return head->val == val? head->next:head;
*/
}
};
474. 一和零
DP
class Solution {
public:
vector<int> getZerosOnes(string &str){
int length = str.length();
vector<int> zerosOnes(2);
for(int i =0; i < length; i++){
zerosOnes[ str[i]-'0' ] ++;
}
return zerosOnes;
}
int findMaxForm(vector<string> &strs, int m, int n){
int length = strs.size();
vector<vector<vector<int>>> dp(length + 1, vector<vector<int>>(m + 1, vector<int>(n + 1)));
for(int i = 1; i <= length; i++){
vector<int> zerosOnes = getZerosOnes(strs[i-1]);
int zeros = zerosOnes[0], ones = zerosOnes[1];
for(int j = 0; j <= m; j++){
for(int k =0; k <= n; k++){
dp[i][j][k] = dp[i - 1][j][k];
if(j>=zeros && k>=ones){
int a = dp[i - 1][j][k];
int b = dp[i - 1][j - zeros][k - ones] + 1;
dp[i][j][k] = max(a, b);
}
}
}
}
return dp[length][m][n];
}
};
797. 所有可能的路径
dfs
class Solution {
public:
vector<vector<int>> ans;
vector<int> temp;
vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {
dfs(graph, 0);
return ans;
}
void dfs(vector<vector<int>> graph, int index){
temp.push_back(index);
if(index == graph.size()-1){
ans.push_back(temp);
temp.pop_back();
return;
}
for(int i = 0; i < graph[index].size(); i++){
dfs(graph, graph[index][i]);
}
temp.pop_back();
}
};
/*
*/
494. 目标和
回溯
class Solution {
public:
int count = 0;
int findTargetSumWays(vector<int> &nums, int target){
backtrack(nums, target, 0, 0);
return count;
}
void backtrack(vector<int> &nums, int target, int index, int sum){
if(index == nums.size()){
if(sum == target){
count++;
}
}else{
backtrack(nums, target, index + 1, sum + nums[index]);
backtrack(nums, target, index + 1, sum - nums[index]);
}
}
};
// 动态规划
class Solution {
public:
//int count = 0;
int findTargetSumWays(vector<int> &nums, int target){
// backtrack(nums, target, 0, 0);
int n = nums.size();
int sum = accumulate(nums.begin(), nums.end(), 0);
int neg = (sum - target);
if(neg % 2 != 0 || neg < 0)
return 0;
neg = neg / 2;
vector<vector<int>> dp(n+1, vector<int>(neg+1));
dp[0][0] = 1;
for(int i = 1; i <=n; i++){
int num = nums[i-1];
for(int j = 0; j <=neg; j++){
dp[i][j] = dp[i-1][j];
if(j>=num){
dp[i][j] = dp[i-1][j] + dp[i-1][j-num];
}
}
}
return dp[n][neg];
}
1049. 最后一块石头的重量 II
// sum - 2*x 当x = mid时,x最大 sum最小
class Solution {
public:
int lastStoneWeightII(vector<int>& stones) {
int len = stones.size();
int sum = accumulate(stones.begin(), stones.end(), 0);
int mid = sum/2;
vector<vector<int>> dp(len+1, vector<int>(mid+1));
for(int i = 1; i <= len; i++){
for(int j = 0; j <= mid; j++){
dp[i][j] = dp[i-1][j];
if(j >= stones[i-1]){
dp[i][j] = max(dp[i-1][j], dp[i-1][j-stones[i-1]] + stones[i-1]);
}
}
}
return sum - 2*dp[len][mid];
}
};
879. 盈利计划
class Solution {
public:
int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) {
int len = group.size();
int MOD = (int)1e9 + 7; // 题目要求
// int m = profit.size();
// 前i个项目中,需要j个人,至少利润为k
vector<vector<vector<int>>> dp(len+1, vector<vector<int>>(n+1, vector<int>(minProfit+1)));
dp[0][0][0] = 1;
for(int i = 1; i <= len; i++){
int earn = profit[i - 1];
int members = group[i - 1];
for(int j = 0; j <= n; j++){
for(int k = 0; k <= minProfit; k++){
dp[i][j][k] = dp[i - 1][j][k];
if(j >= members){
if(k<= earn)
dp[i][j][k] = (dp[i - 1][j][k] + dp[i - 1][j - members][0])%MOD;
else
dp[i][j][k] = (dp[i - 1][j][k] + dp[i - 1][j - members][k-earn])%MOD;
}
}
}
}
int sum = 0;
for(int i = 0; i <= n; i++){
sum = (dp[len][i][minProfit] + sum)% MOD;
/* 测试样例:
10
5
[2,3,5]
[6,7,8]
*/
// cout << dp[len][i][minProfit]; dp[10][i][5]
// 0 0 1 1 0 2 0 1 1 0 1
// 相当于需要的i个人必须全部用上,否则计划数是0的。
}
return sum;
}
};
70. 爬楼梯
// dp[i] = dp[i -1] + dp[i - 2];
// 每一层的方法等于前一层的方法+前面2层的方法
// dp[3] : 1+1+1 , 1+2, 2+1。 3种
// dp[2] : 1+1 2;
// dp[1] : 1;
// ∴ dp[3] = dp[2] + dp[1]
class Solution {
public:
int climbStairs(int n) {
vector<int> dp(n+1);
dp[0] = 1;
dp[1] = 1;
for(int i = 2; i <= n; i++){
dp[i] = dp[i -1] + dp[i - 2];
}
return dp[n];
}
};
// 如果是爬 1,2,5的话
// 状态转移为 dp[i] = dp[i-1] + dp[i-2] + dp[i-5]
int steps[2] = {1,2,5};
for (int i = 1; i <= n; i++){
for (int j = 0; j < 3; j++){
int step = steps[j];
if ( i < step ) continue;// 台阶少于跨越的步数
DP[i] = DP[i] + DP[i-step];
}
}
518. 零钱兑换 II
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<int> dp(amount + 1);
dp[0] = 1;
for (int& coin : coins) {
for (int i = coin; i <= amount; i++) {
dp[i] += dp[i - coin];
}
}
return dp[amount];
}
};
class Solution {
public:
int change(int amount, vector<int>& coins) {
int K = coins.size() + 1;
int I = amount + 1;
int DP[K][I];
//初始化基本状态
for (int k = 0; k < coins.size() + 1; k++){
DP[k][0] = 1;
}
for (int k = 1; k <= coins.size() ; k++){
for (int i = 1; i <= amount; i++){
if ( i >= coins[k-1]) {
DP[k][i] = DP[k][i-coins[k-1]] + DP[k-1][i];
} else{
DP[k][i] = DP[k-1][k];
}
}
}
return DP[coins.size()][amount];
}
};
/*
dp[2] = dp[2] + dp[2-2] = 1 + 1 = 2
dp[3] = dp[3] + dp[3-2] = 1 + 1 = 2
dp[4] = dp[4] + dp[4-2]
dp[10] = dp[10] + dp[10 - 5] = 6 + 4
dp[5] = dp[5] + dp[0] = 3 + 1 = 4
*/
279. 完全平方数
class Solution {
public:
// 判断是否为完全平方数
bool isPerfectSquare(int x) {
int y = sqrt(x);
return y * y == x;
}
// 判断是否能表示为 4^k*(8m+7)
bool checkAnswer4(int x) {
while (x % 4 == 0) {
x /= 4;
}
return x % 8 == 7;
}
int numSquares(int n) {
if (isPerfectSquare(n)) {
return 1;
}
if (checkAnswer4(n)) {
return 4;
}
for (int i = 1; i * i <= n; i++) {
int j = n - i * i;
if (isPerfectSquare(j)) {
return 2;
}
}
return 3;
}
};
// dp[i]理解为 数i的最小完全平方个数。
class Solution {
public:
int numSquares(int n) {
vector<int> dp(n+1);
for(int i = 1; i <= n; i++){
dp[i] = i; //max
for(int j = 1; i - j*j >= 0; j++){
dp[i] = min(dp[i], dp[i - j*j] + 1); // +1 等价于dp[j*j]但是dp[j*j]是完全平方数也就是1
cout<< i <<" "<< dp[i] << " ";
}
cout<<endl;
}
return dp[n];
}
};
278. 第一个错误的版本
难度简单317收藏分享切换为英文接收动态反馈
// The API isBadVersion is defined for you.
// bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
int left = 1, right = n;
int mid = 0;
while(left < right){
// mid = (left + right)/2;
mid = left + (right - left)/2;
if(isBadVersion(mid)){
right = mid;
}else{ //没错
left = mid + 1;
}
}
return left;
}
};
374. 猜数字大小
/**
* Forward declaration of guess API.
* @param num your guess
* @return -1 if num is lower than the guess number
* 1 if num is higher than the guess number
* otherwise return 0
* int guess(int num);
*/
class Solution {
public:
int guessNumber(int n) {
int left = 0, right = n;
int mid = 0;
while(left < right){
mid = left + (right - left)/2;
cout << guess(0);
if(guess(mid) == -1){ // 大于
right = mid -1;
}else if(guess(mid) == 1){ // 小于
left = mid + 1;
}else if(guess(mid) == 0){
return mid;
}
}
return left;
}
};
/*
10 6
5 5<6
left = 5 + 1
6 10
8 8>6
right = 8 - 1 = 7
6 7
6 6==6
*/
852. 山脉数组的峰顶索引
class Solution {
public:
int peakIndexInMountainArray(vector<int>& arr) {
int left = 1, right = arr.size();
int ans;
// 山脉数组只需要判断 arr[i] > arr[i+1]就可以, 因为这种情况就满足了arr[i]>arr[i+1]
// for(int i = 1; i < arr.size(); i++){
// if(arr[i] > arr[i + 1]){
// ans = i;
// break;
// }
// }
// return ans;
while(left < right){
int mid = left + (right - left)/2;
// if(arr[mid] > arr[mid - 1] && arr[mid] > arr[mid + 1]){
// left = mid;
// break;
// }else if(arr[mid] > arr[mid - 1]){
// left = mid + 1;
// }else if(arr[mid] > arr[mid + 1]){
// right = mid - 1;
// }
if(arr[mid] > arr[mid + 1]){
ans = mid;
right = mid;
}else{
left = mid + 1;
}
}
return ans;
}
};
877. 石子游戏
class Solution {
public:
bool stoneGame(vector<int>& piles) {
int length = piles.size();
vector<vector<int>> dp(length, vector<int>(length));
// i和j表示当前的石子堆的数量是j-i, 并且是从i到j的石子堆,dp[i][j]表示i到j中2个玩家拥有石子的最大差值
for(int i = 0; i <length; i++){
dp[i][i] = piles[i];
}
for(int i = length - 2; i >=0; i--){
for(int j = i + 1; j <length; j++){
dp[i][j] = max(piles[i] + dp[i+1][j], piles[j] + dp[i][j-1]); // max是因为对方也要取最大值
}
}
return dp[0][length-1] > 0;
}
};
65. 有效数字
class Solution {
public:
bool hasE, hasNum, isFloat;
bool isNumber(string& s) {
for(int i = 0; i < s.size(); i++) {
char c = s[i];
// 符号位只能在首位或E的后一位
if((c == '-' || c == '+') && (i == 0 || s[i - 1] == 'e' || s[i - 1] == 'E')) {
}else if((c == 'e' || c == 'E') && !hasE && hasNum) {
//只存在一个E, 前面必须有数字, 后面也必须有数字
hasE = true;
hasNum = false;
}else if(c == '.' && !isFloat && !hasE) {
//只存在一个小数点, 不能在E的后面
isFloat = true;
}else if(isdigit(c)) {
hasNum = true;
}else {
return false;
}
}
return hasNum; // flase: '.'
}
};
1239. 串联字符串的最大长度 位运算
// 迭代
class Solution {
public:
int maxLength(vector<string>& arr) {
int ans = 0;
vector<int> masks={0};
for(string &str: arr){
int mask = 0;
// 位运算
// 用一个二进制数来表示该字符串的字符集合,二进制的第 ii 位为 11 表示字符集合中含有第 ii 个小写字母,为 00 表示字符集合中不含有第 ii 个小写字母。
//
for(char ch: str){
ch = ch - 'a';
if((mask >> ch) & 1){ // 去重
mask = 0;
break;
}
mask = mask | 1 << ch; // 再第i位加入当前的字母
}
if(mask == 0){
continue;
}
int n = masks.size();
for(int i = 0; i < n; i++){
int tmp = masks[i];
if((tmp & mask) == 0){
masks.push_back( tmp | mask);
ans = max(ans, __builtin_popcount((tmp | mask)));
}
}
}
return ans;
}
};
// 回溯
class Solution {
private:
void dfs(vector<int>& masks,int pos,int mask,int& ans)
{
if(pos==masks.size())
{
ans=max(ans,__builtin_popcount(mask));//__builtin_popcount()可以用于计算一个 32 位无符号整数有多少个位为1
return;
}
//对于每个字符串都考虑 不选 和 选 两种情况
//不选
dfs(masks,pos+1,mask,ans);
//选
//要选取的话需要首先满足无公共元素
if((mask&masks[pos])==0)//如果无公共元素
{
dfs(masks,pos+1,mask|masks[pos],ans);//如果要选取的话,则把对应的字符加上,即对应二进制位赋予1
}
}
public:
int maxLength(vector<string>& arr)
{
vector<int> masks;
for(auto str:arr)
{
int mask=0;//二进制从右向左起,分别对应a,b,c,d... ...
// eg. a: 1 b: 01 c: 100 d: 1000 abc: 111
for(auto ch:str)
{
ch-='a';//获取当前字符ch从右向左位于二进制的第几个位置
if((mask>>ch)&1)//mask>>ch获取了mask中该位置上是0还是1。如果是1代表该字符已存在
{
mask=0;//则该字符串自身就包含了重复字符,不保留
break;
}
//如果该字符没有重复,则给对应的二进制位赋予1
mask|=1<<ch;
}
if(mask)//如果字符串不等于0,即没有重复字符
{
masks.push_back(mask);
}
}
int ans=0;
dfs(masks,0,0,ans);
return ans;
}
};
1600. 皇位继承顺序
// 这篇算法学到了c++中 成员变量, 字典map<string, vector<string>> tree>, 集合set, 以及最后的迭代器的使用,find
class ThroneInheritance {
public:
string king; // 全局变量
unordered_map<string, vector<string>> tree; // dfs tree
unordered_set<string> dead;
ThroneInheritance(string kingName) {
king = kingName;
}
void birth(string parentName, string childName) {
tree[parentName].push_back(childName); // child value parent key
}
void death(string name) {
dead.insert(name);
}
void dfs(vector<string>& ans, string parentName){ // 注意形参的vector<string>&ans的引用符,否则无法更新。
if(dead.find(parentName) == dead.end()){// find没找到,返回end()
ans.push_back(parentName);
}
for(auto i = tree[parentName].begin(); i != tree[parentName].end(); i++){
dfs(ans, *i); // 必须是*i 类似指针
}
}
vector<string> getInheritanceOrder() {
vector<string> ans;
dfs(ans, king);
return ans;
}
};
401. 二进制手表
__builtin_popcount(num) 计算num的二进制中1的个数。
class Solution {
public:
vector<string> readBinaryWatch(int turnedOn) {
vector<string> ans;
// o(720)
for(int i = 0; i < 12; i++){
for(int j = 0; j < 60; j++){
cout<<__builtin_popcount(i)<<" "<<__builtin_popcount(j)<<endl;
if(__builtin_popcount(i) + __builtin_popcount(j) == turnedOn){
ans.push_back(to_string(i)+":"+(j<10? "0":"")+to_string(j));
}
}
}
return ans;
}
};
// 二进制枚举 一共10个灯,有2^10=1024种灯
class Solution {
public:
vector<string> readBinaryWatch(int turnedOn) {
vector<string> ans;
for (int i = 0; i < 1024; ++i) {
int h = i >> 6, m = i & 63; // 用位运算取出高 4 位和低 6 位
// 1111 | 111111 前4位表示hour,后四位表示minute 因此要获取前4位需要>>操作,需要获取后6位用&操作。
// 判断合理性
if (h < 12 && m < 60 && __builtin_popcount(i) == turnedOn) {
ans.push_back(to_string(h) + ":" + (m < 10 ? "0" : "") + to_string(m));
}
}
return ans;
}
};
剑指 Offer 38. 字符串的排列
class Solution {
public:
vector<string> permutation(string s) {
vector<string> ans;
int pos = 0;
dfs(ans, s, pos);
return ans;
}
void dfs(vector<string> &ans, string &s, int pos){
if(pos == s.size())
ans.push_back(s);
for(int i = pos; i < s.size(); i++){
bool flag = true;
for(int j = pos; j < i; j++){//剪枝 eg. 'aabc' 只有12个排列
if(s[i] == s[j])
flag = false;
}
if(flag){
swap(s[i], s[pos]);
dfs(ans, s, pos + 1);
swap(s[i], s[pos]);
}
}
}
};
// pos = 0 i = 0, j = pos = 0, s[j] = s[i] flag = false, i = 1, j = pos = 0, s[j]!=s[i] if(flag) swap(s[0], s[1])
// abc --> bac dfs(pos+1)
// pos = 1 i = 1, j = pos = 1
// 利用哈希表
class Solution {
public:
unordered_map<char, int> m;
vector<string> ans;
vector<string> permutation(string s) {
for(auto c:s){
m[c]++;
}
int n = s.size();
dfs(n, "");
return ans;
}
void dfs(int n, string s){
if(n == 0){
ans.push_back(s);
return;
}
// 迭代器的使用
unordered_map<char, int>::iterator t;
for(t = m.begin(); t != m.end(); t++){ // 第一种
// for(auto &t: m){ // 第二种
/*
if (t.second){
t.second --;
dfs(n-1, s+t.first);
t.second ++;
}
*/
// 指针
if(t->second){
t->second--;
dfs(n-1, s+t->first);
t->second++;
}
/*
if((*t).second){
(*t).second--;
dfs(n-1, s+(*t).first);
(*t).second++;
}
/*
}
}
};
剑指 Offer 15. 二进制中1的个数
class Solution {
public:
int ans = 0;
int hammingWeight(uint32_t n) {
// int flag;
// for(int i = 0; i < 32; i++){
// flag = n & (1<<i); // n和 2^i
// if(flag)
// ans++;
// }
// 位运算 n = n & (n-1)
// 110 --> 100 --> 000 --> ans = 3
while(n){
n = n&(n-1);
ans++;
}
return ans;
}
};
// 1000001
// 0000001
// 0000010
// 0000100
// 0001000
// 0010000
// 0100000
// 1000000
149. 直线上最多的点数
最后我们再加四个小优化:
- 在点的总数量小于等于 22 的情况下,我们总可以用一条直线将所有点串联,此时我们直接返回点的总数量即可;
- 当我们枚举到点 i 时,我们只需要考虑编号大于 i 的点到点 i 的斜率,因为如果直线同时经过编号小于点 i 的点j,那么当我们枚举到 j时就已经考虑过该直线了;
- 当我们找到一条直线经过了图中超过半数的点时,我们即可以确定该直线即为经过最多点的直线;
- 当我们枚举到点 ii(假设编号从 00 开始)时,我们至多只能找到 n − i n-i n−i个点共线。假设此前找到的共线的点的数量的最大值为 kk,如果有 k ≥ n − i k \geq n-i k≥n−i,那么此时我们即可停止枚举,因为不可能再找到更大的答案了。
// 暴力解法
// 找出2个点, 然后找出第三个点, 计算3点之间的斜率,因为4点可以平行,三点如果斜率相等只有可能共线
class Solution {
public:
int gcd(int a, int b){
if(b == 1){
return gcd(b, a%b);
}
return a;
}
int maxPoints(vector<vector<int>>& points) {
int n = points.size();
int ans = 1;
for(int i = 0; i < n; i++){
vector<int> num1 = points[i];
for(int j = i+1; j < n; j++){
vector<int> num2 = points[j];
int cnt = 2;
for(int k = j+1; k < n; k++){
vector<int> num3 = points[k];
int s1 = (num2[1] - num1[1]) * (num3[0] - num2[0]);
int s2 = (num3[1] - num2[1]) * (num2[0] - num1[0]);
if(s1 == s2)
cnt++;
}
ans = max(ans, cnt);
if(ans > n / 2) return ans; // 当我们找到一条直线经过了图中超过半数的点时,我们即可以确定该直线即为经过最多点的直线;
}
}
return ans;
}
};
// 官方优化
//
// unordered_map<int, int> m;
// unordered_map<string, int> m;
class Solution {
public:
// gcd(0, 25) = 25 因此dy = 25 dx = 0 --> dy = 1, dx = 0
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
// return b==0 ? a: gcd(b, a%b);
}
int maxPoints(vector<vector<int>>& points) {
int n = points.size();
if (n <= 2) {
return n;
}
int ret = 0;
for(int i =0; i < n; i++){
if(ret >= n - i|| ret > n/2)
return ret;
// unordered_map<int, int> m;
unordered_map<string, int> m;
for(int j = i + 1; j < n; j++){
int x = points[i][0] - points[j][0];
int y = points[i][1] - points[j][1];
if(x == 0){ // 为了在map中存储在一样的位置
y = 1;
}else if(y == 0){ // 为了在map中存储在一样的位置
x = 1;
}else if(y<0){ // 为了在map中存储在一样的位置
x = -x;
y = -y;
}
int g = gcd(abs(x), abs(y));
x = x / g, y = y / g;
string s = to_string(x)+"_"+to_string(y);
// cout << s;
// m[y + (20000+1)*x]++;
m[s]++;
}
for(auto &s: m){
ret = max(ret, s.second+1);
}
}
return ret;
}
};
1 -2 -1 2
// 如果用string的方法来存储, 就简便很多 不用考虑那么多
class Solution {
public:
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
int maxPoints(vector<vector<int>>& points) {
int n = points.size();
if (n <= 2) {
return n;
}
int ret = 0;
for(int i =0; i < n; i++){
if(ret >= n - i|| ret > n/2)
return ret;
// unordered_map<int, int> m;
unordered_map<string, int> m;
for(int j = i + 1; j < n; j++){
int x = points[i][0] - points[j][0];
int y = points[i][1] - points[j][1];
/*
if(x == 0){ // 为了在map中存储在一样的位置
y = 1;
}else if(y == 0){ // 为了在map中存储在一样的位置
x = 1;
}else if(y<0){ // 为了在map中存储在一样的位置
x = -x;
y = -y;
}
*/
int g = gcd(x, y);
x = x / g, y = y / g;
string s = to_string(x)+"_"+to_string(y);
// cout << s;
// m[y + (20000+1)*x]++;
m[s]++;
}
for(auto &s: m){
ret = max(ret, s.second+1);
}
}
return ret;
}
};
752. 打开转盘锁(BFS)
做了很久,要点有:多维vector的赋值。
BFS的思路。
char a = 'a';
a = a + 2 # 'c'
a - 'a' # 2
'1' - '0' # 1
'1' + 1 # '2'
// temp[i] = '1';
// cout<<'1' - '0' << endl;
// cout<<temp[i]<<endl;
// cout<< temp[i] + 1<<endl;
// cout<< temp[i] + '1'<<endl;
// cout<<temp[i] - '1'<<endl;
// cout<<temp[i] + 1 - '0'<< endl;
// cout<<temp[i] + '1' - '0'<< endl;
// 相比较于下一题, 我这样子的思路不太好
// 最好还是 q.empty q.size() 然后遍历q的节点这样
class Solution {
public:
int openLock(vector<string>& deadends, string target) {
// vector<int> ans(10, 0); 10 rows, value of 0
// vector<vector<int>> ans(10, vector<int>(10));
if(target == "0000")
return 0;
// 多维vector的赋值 千万不要写错
vector<vector<vector<vector<bool>>>> visited(10, vector<vector<vector<bool>>>(10, vector<vector<bool>>(10, vector<bool>(10, false)))); // bool[10][10][10][10] represents 0000~ 9999
for(auto &str: deadends){
if(str == "0000")
return -1;
visited[str[0]-'0'][str[1]-'0'][str[2]-'0'][str[3]-'0'] = true;
}
queue<string> q;
q.push("0000"); // init
visited[0][0][0][0] = true;
int len_queue = 1;
int ans = 0;
// bfs
while(!q.empty()){
// ans
if(q.front() == target){
// ans++;
break;
}
string temp;
for(int i = 0; i < target.size(); i++){
// add
// eg. 0000 --> 1000; 9000 --> 0000
temp = q.front();
if(temp[i] == '9')
temp[i] = '0';
else
temp[i] = temp[i] + 1;
if(!visited[temp[0] - '0'][temp[1] - '0'][temp[2] - '0'][temp[3] - '0']){
q.push(temp);
visited[temp[0] - '0'][temp[1] - '0'][temp[2] - '0'][temp[3] - '0'] = true;
}
// substract
// eg. 0000 --> 9000; 9000 -> 8000
// need to redirect
temp = q.front();
if(temp[i] == '0')
temp[i] = '9';
else
temp[i] = temp[i] - 1;
if(!visited[temp[0] - '0'][temp[1] - '0'][temp[2] - '0'][temp[3] - '0']){
q.push(temp);
visited[temp[0] - '0'][temp[1] - '0'][temp[2] - '0'][temp[3] - '0'] = true;
}
}
q.pop();
len_queue--;
if(len_queue == 0){
len_queue = q.size();
ans++;
}
}
if(q.empty())
return -1;
return ans;
}
};
773. 滑动谜题(BFS)
BFS 问题
while(!q.empty())
while(q.size()--){
if q.front() == ans
return cnt;
// first visited
if set.count(q.front()){
q.pop()
continue
}else{
set.insert(q.front)
}
for(int i = 0; i < node.size(); i++)
// then visited
tmp = q.front do some opeartion
if(set.count(tmp))
continue
else
q.push(temp)
q.pop()
}
class Solution {
public:
int slidingPuzzle(vector<vector<int>>& board) {
vector<vector<int>> neighbours = {{1, 3}, {0, 2, 4}, {1,5}, {0, 4}, {1, 3, 5}, {2, 4}};
// 优化 queue里面的每一个元素为 string
//queue<vector<vector<int>>> q;
queue<string> q;
unordered_set<string> set; // 用set来过滤已经出现的情况(不满足,就不是最小次数)
string b;
for(int i = 0; i < board.size(); i++){
for(int j = 0; j < board[0].size(); j++){
b += board[i][j] + '0';
}
}
int ans = 0;
q.push(b);
while(!q.empty()){
int n = q.size();
for(int i = 0; i < n; i++){
// 先放入q中 在去重
// 或者可以在下面的for中先判断,不满足条件就不放入队列中
if(q.front() == "123450"){
return ans;
}
// 去重方案1
// if(set.count(q.front())){
// q.pop();
// continue;
// }else{
// set.insert(q.front());
// }
int pos = q.front().find("0");
for(auto &i : neighbours[pos]){
string temp = q.front();
swap(temp[pos], temp[i]);
// 去重方案2
if(set.count(temp)){
continue;
}else{
set.insert(temp);
}
q.push(temp);
}
q.pop();
}
ans++;
}
if(q.empty())
return -1;
return ans;
}
};
5797. 两个数对之间的最大乘积差(sort)
class Solution {
public:
static bool compare(int a, int b){
return a > b;
}
int maxProductDifference(vector<int>& nums) {
sort(nums.begin(), nums.end(), compare);
return (nums[0] * nums[1]) - (nums[nums.size()-1] * nums[nums.size()-2]);
}
};
// 5 6 2 7 4
// mx1 mx2
// 6 5
// mn1 mn2
// 5 6
// for 2 7 4
// 6 5
// 2 5
// 7 6
// 2 5
// 7 6
// 2 4
815. 公交路线
(认真严肃!!!int n = q.size())
别给我省下这一步:!!! 不要眼高手低 觉得浪费时间
while(!q.empty()){
int n = q.size(); // 要想正序排列 必须先存储!!!!因为在后面的for循环中有q.pop()这个操作,如果你是i<q.size() 那么size会随着pop()操作变化。
for(int i = 0; i < n; i++){
// 逆序直接写
for(int i = q.size()-1; i>=0; i--)
// 这题的bfs 中, 多一个for 循环 并且set去重 以及 return 判断target 是否和当前队列头元素相等的操作 也不太一样。 需要更加理解题目 套公式
// 需要创建一个map优化 map[i] = {j,....} 表示 车站i 所在的公交线路有j,...
// 因为是判断最少公交线路, 因此去重去的是route.size()的值 也就是有多少线路,最大不超过route.size()
class Solution {
public:
int numBusesToDestination(vector<vector<int>>& routes, int source, int target) {
if(source == target)
return 0;
queue<int> q;
int ans = 1;
q.push(source);
unordered_map<int, vector<int>> m;
unordered_set<int> set;
for(int i = 0; i < routes.size(); i++){
for(auto &j : routes[i]){
m[j].push_back(i);
}
}
while(!q.empty()){
int n = q.size();
for(int i = 0; i < n; i++){
int frontStation = q.front();
for(auto &routeIndex: m[frontStation]){
if(set.count(routeIndex)){
continue;
}else{
set.insert(routeIndex);
for(const auto &station: routes[routeIndex]){
if(station == target){
return ans;
}
q.push(station);
}
}
}
q.pop();
}
ans++;
}
return -1;
}
};
168. Excel表列名称
虽然是简单题,但是我还是遇到了2个坑,首先是char 和string拼接的问题。使用+=
or push_back()
。
y += d;
In gcc, basic_string::operator+= is just a call in push_back
std::string y("Hello world");
y.push_back('d')
std::cout << y;
另外这2个方法涉及自动强制转换int–> char。
string ans="";
cout<<2+'A'-1<<endl; // 66 不是我们需要的答案
// 使用+= 操作相当于 强制转换了。
cout<< (char)(2+'A'-1)<<endl; // B
ans += 2 + 'A' - 1; // B
// 使用push_back
string ans="";
ans.push_back(2+'A'-1);
ans.push_back(2+'A'-1);
cout << ans; // "AA"
对于10进制转为X进制的方法:
while(num!=0){
temp = num % X; // 得到余数
num = num / X; // 得到除数
}
这题比较特殊,虽然是26进制转换,本来是26—》10;但是它要求在26的时候等于Z。
//一般性的进制转换题目无须进行额外操作,是因为我们是在「每一位数值范围在 [0,x)的前提下进行「逢 x 进一」。
//本题需要我们将从 1 开始,因此在执行「进制转换」操作前,我们需要先对 columnNumbercolumnNumber 执行减一操作,从而实现整体偏移。
class Solution {
public:
string convertToTitle(int columnNumber) {
string ans = "";
while(columnNumber != 0){
columnNumber--;
int temp = (columnNumber) % 26;
ans += temp + 'A';
columnNumber = (columnNumber) / 26;
}
// string res;
// for(int i = ans.size()-1; i >= 0; i--){
// res.push_back(ans[i]);
// }
reverse(ans.begin(), ans.end()); // 翻转方法
return ans;
}
};
剑指 Offer 37. 序列化二叉树
codec.deserialize(codec.serialize(root));
这段代码的意思就是其实里面是你自己设计,但是你要自圆其说,保证 encoder-decoder后的结果一样
你可以是1,2,X,X,3,4,5
也可以是1,2,None,None,3,4,5
也可以是1,2,3,X,X,4,5,
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));
class Codec {
public:
// 先序遍历
void rserialize(TreeNode* root, string& str) {
if (root == nullptr) {
str += "null,";
} else {
// to_string
str += to_string(root->val) + ",";
rserialize(root->left, str);
rserialize(root->right, str);
}
}
string serialize(TreeNode* root) {
string ret;
rserialize(root, ret);
return ret;
}
TreeNode* rdeserialize(list<string>& dataArray) {
if (dataArray.front() == "null") {
dataArray.erase(dataArray.begin()); //删除保证 下一次取到新的元素
return nullptr;
}
// stoi
TreeNode* root = new TreeNode(stoi(dataArray.front()));
dataArray.erase(dataArray.begin()); //删除保证 下一次取到新的元素
// 依次遍历 左右子树
root->left = rdeserialize(dataArray);
root->right = rdeserialize(dataArray);
return root;
}
// list<strig>
TreeNode* deserialize(string data) {
list<string> dataArray;
string str;
for (auto& ch : data) {
if (ch == ',') { //split
dataArray.push_back(str);
str.clear();
} else {
str.push_back(ch);
}
}
// for(auto &ls: dataArray)
// cout<<ls;
// if (!str.empty()) {
// dataArray.push_back(str);
// str.clear();
// }
return rdeserialize(dataArray);
}
};
LCP 07. 传递信息 (邻接矩阵)
本题的关键在于创建数据结构 图中的邻接矩阵,对于NxN的relation,可以用vector控制每一个结点的x条边。(就不用提前设置好nxn的矩阵。
// BFS
// 队列中示例
// 0 1 2 3
// 0, 2, 4, 1, 3, 0, 4, 4, 2, 4
class Solution {
public:
int numWays(int n, vector<vector<int>>& relation, int k) {
// 邻接矩阵
vector<vector<int>> edges(n); // vector<vector<int>> edges(n, vector<int>(n))
for(auto &edge : relation){
int x = edge[0], y = edge[1]; // x --> y
edges[x].push_back(y);
}
queue<int> q;
q.push(0);
int ans = 0;
int step = 0;
// 需要设置一个step来控制循环时间
while(!q.empty() && step < k){
step++;
int n = q.size();
for(int i = 0; i < n; i++){
int temp = q.front();
q.pop();
// 与q.front()有边的结点入队
for(auto &node: edges[temp]){
q.push(node);
}
}
}
//
while(!q.empty()){
int temp = q.front();
q.pop();
if(temp == n-1)
ans++;
}
return ans;
}
};'
// dfs
class Solution {
public:
int ans = 0;
int step = 0;
int numWays(int n, vector<vector<int>>& relation, int k) {
// 邻接矩阵
vector<vector<int>> edges(n);
for(auto &edge : relation){
int x = edge[0], y = edge[1]; // x --> y
edges[x].push_back(y);
}
dfs(0, 0, edges, k, n);
return ans;
}
void dfs(int index, int step, vector<vector<int>> &edges, int k, int n){
if(step == k){
if(index == n-1){
ans++;
}
return;
}
for(auto &egde: edges[index])
dfs(egde, step+1, edges, k, n);
}
};
451. 根据字符出现频率排序(pair 排序)
// map 不能直接使用sort函数
// 需要先把 map 的元素存成pair
class Solution {
public:
static bool compare(pair<char, int> a, pair<char, int> b){
return a.second > b.second;
}
string frequencySort(string s) {
map<char, int> m;
vector<pair<char, int>> v; // pair元素的vector
for(auto &str: s){
m[str]++;
}
for(auto &it: m){ // it 就是 pair<char, int> 因此可以直接输入
v.push_back(it);
}
sort(v.begin(), v.end(), compare);
string ans = "";
for(int i = 0; i < v.size(); i++){
for(int j = 0; j < v[i].second; j++)
ans.push_back(v[i].first);
}
return ans;
}
};
645. 错误的集合
数学方法,求1+2...+N的和,nums唯一set()的和,和nums的和对应做减法直接得到结果
class Solution:
def findErrorNums(self, nums: List[int]) -> List[int]:
S = sum(set(nums))
return [sum(nums)-S ,len(nums)*(len(nums)+1)//2-S]
class Solution {
public:
vector<int> findErrorNums(vector<int>& nums) {
vector<int> rec(nums.size() + 1);
for(auto &num: nums){
rec[num]++;
}
vector<int> ans;
int copy_num = -1;
int left_num = -1;
bool flag_copy = false;
bool flag_left = false;
for(int i = 1; i < nums.size() + 1; i++){
if(flag_copy && flag_left)
break;
if(rec[i] > 1){
copy_num = i;
flag_copy = true;
}
if(left && rec[i] ==0){
left_num = i;
flag_left = true;
}
}
ans.push_back(copy_num);
ans.push_back(left_num);
return ans;
}
};
1418. 点菜展示表
class Solution {
public:
vector<vector<string>> displayTable(vector<vector<string>>& orders) {
unordered_map<int, unordered_map<string, int>> foodNum;
// map <int, string> 3: (x:0 y:1 z:2)
unordered_set<string> foodSet;
for(auto &order: orders){
foodSet.insert(order[2]);
foodNum[stoi(order[1])][order[2]]++;
}
// sort_food
vector<string> sort_food;
for(auto &food: foodSet){
sort_food.push_back(food);
}
sort(sort_food.begin(), sort_food.end());
// sort_table
vector<int> sort_table;
for(auto &table: foodNum){
sort_table.push_back(table.first);
}
sort(sort_table.begin(), sort_table.end());
vector<vector<string>> ans(sort_table.size() + 1);
ans[0].push_back("Table");
// row - table
for(int i = 1; i < sort_table.size() + 1; i++){
ans[i].push_back(to_string(sort_table[i - 1]));
// cout << to_string(sort_table[i - 1]) << endl;
}
// column - food
for(int i = 1; i < sort_food.size() + 1; i++){
ans[0].push_back(sort_food[i - 1]);
// cout << sort_food[i - 1] << endl;
}
// cout << foodNum[sort_table[0]][sort_food[3]];
for(int i = 1; i < sort_table.size() + 1; i++){
unordered_map<string, int> each_table = foodNum[sort_table[i - 1]];
for(int j = 1; j < sort_food.size() + 1; j++){
// ans[i].push_back(sort_food[j - 1]);
string each_table_food = sort_food[j - 1];
string each_food_num = to_string(each_table[each_table_food]);
ans[i].push_back(each_food_num);
}
}
return ans;
}
};
1711. 大餐计数
class Solution {
public:
static constexpr int MOD = 1'000'000'007;
int countPairs(vector<int>& deliciousness) {
int maxVal = *max_element(deliciousness.begin(), deliciousness.end());
int maxSum = maxVal * 2;
int pairs = 0;
unordered_map<int, int> mp;
int n = deliciousness.size();
for (auto& val : deliciousness) {
for (int sum = 1; sum <= maxSum; sum <<= 1) {
int count = mp.count(sum - val) ? mp[sum - val] : 0;
pairs = (pairs + count) % MOD;
}
mp[val]++;
}
return pairs;
}
};
面试题 17.10. 主要元素
// 朴素解法 max_element的使用 利用map.value 取最大值,需要做一个compare自定义函数.
class Solution {
public:
static bool compare(pair<int, int> num1, pair<int, int> num2){
return num1.second < num2.second;
}
int majorityElement(vector<int>& nums) {
unordered_map<int, int> mp;
for(int i = 0; i < nums.size(); i++){
mp[nums[i]]++;
}
// 1 1 4 2
vector<pair<int, int>> v;
pair<int ,int> maxval = *max_element(mp.begin(), mp.end(), compare);
if(maxval.second > nums.size()/2)
return maxval.first;
return -1;
}
};
// 朴素解法
class Solution {
public:
int majorityElement(vector<int>& nums) {
unordered_map<int, int> mp;
for(int i = 0; i < nums.size(); i++){
mp[nums[i]]++;
if(mp[nums[i]] * 2 > nums.size())
return nums[i];
}
return -1;
}
};
// 摩尔投票
class Solution {
public:
int majorityElement(vector<int>& nums) {
int candidate = -1;
int count = 0;
for (int& num : nums) {
if (count == 0) { // count = 0 加入新元素
candidate = num;
}
if (num == candidate) { // 比较每次的元素和候选元素是否相等
count++; // 相等则 count++
} else {
count--; // 否则 count--
}
}
count = 0;
int length = nums.size();
for (int& num : nums) { // 遍历所有元素,找到等于候选元素的个数
if (num == candidate) {
count++;
}
}
return count * 2 > length ? candidate : -1; // 如果count*2 大于数组长度则表明找到元素。
}
};
// 2 2 1 1 1 2 2
// num = 2 count == 0 cand = 2 cout++
// num = 2 cand = num count++ = 2
// num = 1 count!=0 cand != num cout-- = 1
// num = 1 count!=0 cout-- = 0
// num = 1 count == 0 cand = num = 1 cout++
// num = 2 count!=0 cand!=num cout-- = 0
// num = 2 count == 0 cand = num = 2 cout++
// for(num : nums)
// if num == cand
cout_final++
// return cou_final * 2 > size()? candidate:-1;
// 1 2 5 9 5 5 5
// 5
// candidiate = 1 num = 1 count++ = 1
// num = 2 num !=candidate count-- = 0
// num = 5 count = 0 candidata = 5 count++ = 1
// num = 9 count!=0 num!=candidate cout-- = 0
// num = 5 count == 0 candidata = num = 9 cout++
// num = 5 count!= 0 num == candidite = 5 cout++
// count++ = 3
H 指数 II
class Solution {
public:
int hIndex(vector<int>& citations) {
for(int i = 0; i < citations.size(); i++){
int h = citations.size() - i;
if(citations[i] >= h){
return h;
}
}
return 0;
}
};
// 二分
class Solution {
public:
int hIndex(vector<int>& citations) {
// for(int i = 0; i < citations.size(); i++){
// int h = citations.size() - i;
// if(citations[i] >= h){
// return h;
// }
// }
// return 0;
int n = citations.size();
int left = 0, right = n - 1;
while(left <= right){
int mid = left + (right - left) / 2;
if(citations[mid] >= citations.size() - mid){ //
right = mid - 1;
}else{
// 2 2 + 2 = 4
left = mid + 1;
}
}
return n- left;
}
};