date:2024-11-1 tag:动态规划
题解 使用动态规划解题,分别定义dpA[i]``dpB[i]
为时间i时的最大总强化能量。 结果为long long型,定义vectordpA(n,0)同时初始化dpA[0]。 动态转移方程dpA[i]=max(dp[i-1],dpB[i-2])+energyDrinkA[i]
考虑i=1时,可能为选i=0后就2切换。(i>1?dpB[i-2]:0) 返回max(dpA[n-1],dpB[n-1])
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution {public : long long maxEnergyBoost (vector<int >& energyDrinkA, vector<int >& energyDrinkB) { int n=energyDrinkA.size (); vector<long long >dpA (n,0 ); vector<long long >dpB (n,0 ); dpA[0 ]=energyDrinkA[0 ]; dpB[0 ]=energyDrinkB[0 ]; for (int i=1 ;i<n;++i){ dpA[i]=max (dpA[i-1 ],(i>1 ?dpB[i-2 ]:0 ))+energyDrinkA[i]; dpB[i]=max (dpB[i-1 ],(i>1 ?dpA[i-2 ]:0 ))+energyDrinkB[i]; } return max (dpA[n-1 ],dpB[n-1 ]); } };
date:2024-11-2 tag:DFS
题解 用深度优先搜索,res
为结果,current
为中间搜索数组。targetSum
为0且当前位置root
左右子树为空时,表示找到了一个结果,加入到res中。 否则就遍历左或右子树,root为空时,表示找不到结果,直接返回return,root不为空,更新targetSum值,将当前的root->val加入到current中。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Solution {public : void dfs (TreeNode*root,vector<vector<int >>&res,int targetSum,vector<int >¤t) { if (root==nullptr )return ; current.emplace_back (root->val); targetSum-=root->val; if (targetSum==0 &&root->left==nullptr &&root->right==nullptr ){ res.emplace_back (current); }else { dfs (root->left,res,targetSum,current); dfs (root->right,res,targetSum,current);} current.pop_back (); } vector<vector<int >> pathSum (TreeNode* root, int targetSum) { vector<vector<int >>res; vector<int >current; dfs (root,res,targetSum,current); return res; } };
date:2024-11-3 tag:深度优先搜索
题解 初始化res为0,current表示中间未达到叶子节点的数,每次遍历如果root不为空,更新current
的值, 如果左右节点都为空,将current的值加入到结果中,退出此次遍历。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution {public : void dfs (TreeNode* root,int &res,int current) { if (root==nullptr )return ; current=current*10 +root->val; if (root->left==nullptr &&root->right==nullptr ){ res+=current; return ; } dfs (root->left,res,current); dfs (root->right,res,current); } int sumNumbers (TreeNode* root) { int res=0 ; dfs (root,res,0 ); return res; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 func dfs (root *TreeNode,current int ,res *int ) { if root==nil { return } current=current*10 +root.Val if root.Left==nil &&root.Right==nil { *res+=current return } dfs(root.Left,current,res) dfs(root.Right,current,res) } func sumNumbers (root *TreeNode) int { res:=0 dfs(root,0 ,&res) return res }
date:2024-11-4 tag:双指针
题解 假设left<=right,初始化left=0,right=$\sqrt{c}$
$left^2$$+$$right^2$=c,找到结果返回true
$left^2$$+$$right^2$>c,减少右边界
$left^2$$+$$right^2$<c,增加左边界
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution {public : bool judgeSquareSum (int c) { long left=0 ,right=(int )sqrt (c); while (left<=right){ long sum=left*left+right*right; if (sum==c)return true ; else if (sum<c){ left++; } else { right--; } } return false ; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 func judgeSquareSum (c int ) bool { left,right:=0 ,int (math.Sqrt(float64 (c))) for left<=right{ sum:=left*left+right*right if sum==c{ return true }else if sum>c{ right-- }else { left++ } } return false }
date:2024-11-5
题解 bool isAliceturn表示现在需要Alice操作,没有改变状态表示Alice失败,Bob胜利,否则为Bob, 需要拿出总值为115的硬币,实际固定需要1枚75,4枚10。
代码 1 2 3 4 5 6 7 8 9 10 11 12 class Solution {public : string losingPlayer (int x, int y) { bool isAliceturn=true ; while (x>=1 &&y>=4 ){ isAliceturn=!isAliceturn; x-=1 ; y-=4 ; } return isAliceturn?"Bob" :"Alice" ; } };
1 2 3 4 5 6 7 8 9 10 11 12 func losingPlayer (x int , y int ) string { isAliceturn:=true for x>=1 &&y>=4 { isAliceturn=!isAliceturn x-=1 y-=4 } if (isAliceturn){ return "Bob" } return "Alice" }
date:2024-11-6 tag:数组
题解 初始化result
数组存放结果,外循环遍历长度为k的子数组,用isincreating
表示数组是否递增, 内循环遍历子数组,j=i+1
便于比较nums[j]-nums[j-1]!=1
是否递增,不至于越界,返回外循环,以iscreaing的值得出题目中的能量值。nums.begin()+i,nums.begin()+i+k
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution {public : vector<int > resultsArray (vector<int >& nums, int k) { int n=nums.size (); vector<int >result; for (int i=0 ;i<=n-k;++i){ bool isincreaing=true ; for (int j=i+1 ;j<i+k;++j){ if (nums[j]-nums[j-1 ]!=1 ){ isincreaing=false ; break ; } } if (isincreaing){ result.push_back (*max_element (nums.begin ()+i,nums.begin ()+i+k)); }else { result.push_back (-1 ); } } return result; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 func findMax (nums []int ) int { maxElem := nums[0 ] for _, num := range nums { if num > maxElem { maxElem = num } } return maxElem } func resultsArray (nums []int , k int ) []int { n:=len (nums); result:=[]int {} for i:=0 ;i<=n-k;i++{ isIncreaing:=true for j:=i+1 ;j<i+k;j++{ if nums[j]-nums[j-1 ]!=1 { isIncreaing=false break } } if isIncreaing{ maxNumber:=findMax(nums[i:i+k]) result=append (result,maxNumber) }else { result=append (result,-1 ) } } return result }
date:2024-11-7 tag:滑动窗口
题解 这道题和前一道题相同,但是nums的大小提升导致不能for循环里面嵌套循环了,会超时。 直接在nums数组中找到连续上升的个数,表示为cnt,结果数组res大小为n-k+1
, 遍历nums,初始化cnt为0,i=0
或nums[i]-nums[i-1]==1
表示连续上升,增加cnt的值,否则为1 如果发现 cnt≥k,那么下标从 i−k+1 到 i 的这个子数组的能量值为 nums[i],即 ans[i−k+1]=nums[i]。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution {public : vector<int > resultsArray (vector<int >& nums, int k) { int n=nums.size (); vector<int >res (n-k+1 ,-1 ); int cnt=0 ; for (int i=0 ;i<n;++i){ if (i==0 )cnt++; else if (nums[i]-nums[i-1 ]==1 )cnt++; else cnt=1 ; if (cnt>=k){ res[i-k+1 ]=nums[i]; } } return res; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 func resultsArray (nums []int , k int ) []int { res:=make ([]int ,len (nums)-k+1 ) for i:=range res{ res[i]=-1 } cnt:=0 for i,cur:=range nums{ if i==0 ||cur==nums[i-1 ]+1 { cnt++ }else { cnt=1 } if cnt>=k{ res[i-k+1 ]=cur } } return res }
date:2024-11-8 tag:栈
题解 变量声明:使用 countStack 和 stringStack 作为堆栈,分别保存计数和字符串部分。 循环解析字符串:通过 for 循环遍历字符串 s 的每个字符: 若字符为数字(0-9),构造 k 的值。 遇到 ‘[‘ 时,将 k 和 current 推入堆栈,并重置它们。 遇到 ‘]’ 时,从堆栈中弹出计数并重复 current,再将结果组合到之前的字符串。 其他字符则直接添加到 current。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 func decodeString (s string ) string { count:=[]int {} stackString:=[]string {} current:="" k:=0 for _,c:=range s{ if c>='0' &&c<='9' { num,_:=strconv.Atoi(string (c)) k=k*10 +num }else if c=='[' { count=append (count,k) stackString=append (stackString,current) k=0 current="" }else if c==']' { repeatCount:=count[len (count)-1 ] count=count[:len (count)-1 ] decodedString:=stackString[len (stackString)-1 ] stackString=stackString[:len (stackString)-1 ] decodedString+=strings.Repeat(current,repeatCount) current=decodedString }else { current+=string (c) } } return current }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution {public : string decodeString (string s) { stack<int >count; stack<string>stackString; string current; int k=0 ; for (char c:s){ if (isdigit (c)){ k=k*10 +(c-'0' ); }else if (c=='[' ){ count.push (k); stackString.push (current); k=0 ; current.clear (); }else if (c==']' ){ int reaptedCount=count.top ();count.pop (); string decodedString=stackString.top ();stackString.pop (); while (reaptedCount-->0 ){ decodedString+=current; } current=decodedString; }else { current+=c; } } return current; } };
date:2024-11-8 tag:哈希表
题解 将数组存入哈希表中,便于快速查找, 遍历哈希表元素,如果未找到元素setNum-1
表示其不在集合中,更新序列起点,和当前的长度。 从当前setNum开始,检查setNum+1
,setNum+2
是否在集合中,记录当前连续序列的长度currenLength. 最后更新最大长度。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution {public : int longestConsecutive (vector<int >& nums) { unordered_set<int >set (nums.begin (),nums.end ()); int longestLength=0 ; for (int setNum:set){ if (!set.count (setNum-1 )){ int currentNum=setNum; int currentLength=1 ; while (set.count (currentNum+1 )){ currentLength+=1 ; currentNum+=1 ; } longestLength=max (longestLength,currentLength); } } return longestLength; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 func longestConsecutive (nums []int ) int { set:=make (map [int ]bool ) longestLength:=0 for _,num:= range nums{ set[num]=true } for num:= range set{ if _,exists:=set[num-1 ];!exists{ currentLength:=1 ; currentNum:=num for { if _,exists:=set[currentNum+1 ];exists{ currentLength+=1 ; currentNum+=1 ; }else { break } } if currentLength>longestLength { longestLength=currentLength } } } return longestLength }
date:2024-11-9 tag:哈希表
题解 用hashmap存放二维数组的值和值在数组所在的位置, 用direction存放元素相邻移动和对角线移动位置的变化 根据哈希表找到元素值所在的位置,通过遍历direction访问邻居和对角线元素。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 class NeighborSum {private : vector<vector<int >>grid; unordered_map<int ,pair<int ,int >>pos; public : NeighborSum (vector<vector<int >>& grid) :grid (grid){ int n=grid.size (); for (int i=0 ;i<n;++i){ for (int j=0 ;j<n;++j){ pos[grid[i][j]]={i,j}; } } } int adjacentSum (int value) { if (pos.find (value)==pos.end ())return 0 ; int sum=0 ; int x=pos[value].first; int y=pos[value].second; vector<pair<int ,int >>dir{{1 ,0 },{-1 ,0 },{0 ,1 },{0 ,-1 }}; for (auto d:dir){ int dx=x+d.first; int dy=y+d.second; if (dx>=0 &&dx<grid.size ()&&dy>=0 &&dy<grid.size ()){ sum+=grid[dx][dy]; } } return sum; } int diagonalSum (int value) { if (pos.find (value)==pos.end ())return 0 ; int sum=0 ; int x=pos[value].first; int y=pos[value].second; vector<pair<int ,int >>dir{{-1 ,-1 },{1 ,1 },{1 ,-1 },{-1 ,1 }}; for (auto d:dir){ int dx=x+d.first; int dy=y+d.second; if (dx>=0 &&dx<grid.size ()&&dy>=0 &&dy<grid.size ()){ sum+=grid[dx][dy]; } } return sum; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 type NeighborSum struct { grid [][]int valuePosition map [int ][2 ]int } func Constructor (grid [][]int ) NeighborSum { valuePosition := make (map [int ][2 ]int ) for i := 0 ; i < len (grid); i++ { for j := 0 ; j < len (grid[i]); j++ { valuePosition[grid[i][j]] = [2 ]int {i, j} } } return NeighborSum{ grid: grid, valuePosition: valuePosition, } } func (this *NeighborSum) AdjacentSum(value int ) int { pos, exists := this.valuePosition[value] if !exists { return 0 } x, y := pos[0 ], pos[1 ] sum := 0 directions := [][2 ]int {{-1 , 0 }, {1 , 0 }, {0 , -1 }, {0 , 1 }} for _, dir := range directions { nx, ny := x+dir[0 ], y+dir[1 ] if nx >= 0 && nx < len (this.grid) && ny >= 0 && ny < len (this.grid[0 ]) { sum += this.grid[nx][ny] } } return sum } func (this *NeighborSum) DiagonalSum(value int ) int { pos, exists := this.valuePosition[value] if !exists { return 0 } x, y := pos[0 ], pos[1 ] sum := 0 diagonals := [][2 ]int {{-1 , -1 }, {-1 , 1 }, {1 , -1 }, {1 , 1 }} for _, diag := range diagonals { nx, ny := x+diag[0 ], y+diag[1 ] if nx >= 0 && nx < len (this.grid) && ny >= 0 && ny < len (this.grid[0 ]) { sum += this.grid[nx][ny] } } return sum }
date:2024-11-10 tag:二分查找
题解 此题用二分查找解题,初始化左右边界left和right,用nums[mid]表示中间元素,nums[mid^1]表示邻居元素。nums[mid]==nums[mid^1]
说明有值相同的邻居元素,单独的元素在右半部分,left=mid+1
更改左边界 否则更改右边界,right=mid;^
为异或运算,对于两个二进制位,如果它们相同则结果是 0,如果它们不同则结果是 1。mid ^ 1
的作用:实际上是将 mid 的最低有效位(即最后一位)取反:
如果 mid
是 偶数,最低有效位是 0,则 mid ^ 1
会使最低有效位变为 1,结果是 mid + 1
。 如果 mid
是 奇数,最低有效位是 1,则 mid ^ 1
会使最低有效位变为 0,结果是 mid - 1
。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution {public : int singleNonDuplicate (vector<int >& nums) { int left=0 ,right=nums.size ()-1 ; while (left<right){ int mid=left+(right-left)/2 ; if (nums[mid]==nums[mid^1 ]){ left=mid+1 ; }else { right=mid; } } return nums[left]; } };
1 2 3 4 5 6 7 8 9 10 11 12 func singleNonDuplicate (nums []int ) int { left,right:=0 ,len (nums)-1 for left<right{ mid:=left+(right-left)/2 if nums[mid]==nums[mid^1 ]{ left=mid+1 }else { right=mid; } } return nums[left] }
date:2024-11-10 tag:二叉树
题解 向左子树遍历时,把当前的val
设为最大边界,右子树遍历时,将当前的val
设为最小边界。 向下遍历时,超过无论是最大还是最小边界都不是二叉搜索树,返回false 结束条件,root为空表示没有超出边界过,返回true
用maxVal
和minVal
确保初始化不会超出边界。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 func isValidFunc (root *TreeNode,minVal,maxVal int ) bool { if root==nil { return true } if root.Val>=maxVal||root.Val<=minVal{ return false } return isValidFunc(root.Left,minVal,root.Val)&&isValidFunc(root.Right,root.Val,maxVal) } func isValidBST (root *TreeNode) bool { return isValidFunc(root,math.MinInt64,math.MaxInt64) }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution {public : bool isValidfunc (TreeNode* root,long long minVal,long long maxVal) { if (root==nullptr )return true ; if (root->val<=minVal||root->val>=maxVal)return false ; return isValidfunc (root->left,minVal,root->val)&&isValidfunc (root->right,root->val,maxVal); } bool isValidBST (TreeNode* root) { return isValidfunc (root,LONG_MIN,LONG_MAX); } };
date:2024-11-11 tag:动态规划
题解 定义 dp[i][j] 表示将木棍区间 [i, j] 之间的部分切割成若干段的最小总成本。 dp[0][n] 是最终答案,表示整个木棍的最小切割成本。 len 表示区间的长度,i 是区间的左端点,j 是区间的右端点。 对于每一个区间 [i, j],我们遍历其中的每一个中间切割点 k,并计算出最小的切割成本。 更新 dp[i][j] 为每次切割的最小成本。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution {public : int minCost (int n, vector<int >& cuts) { cuts.push_back (0 ); cuts.push_back (n); sort (cuts.begin (),cuts.end ()); int m=cuts.size (); vector<vector<int >>dp (m,vector <int >(m,0 )); for (int len=2 ;len<m;++len){ for (int i=0 ;i<m-len;++i){ int j=i+len; dp[i][j]=INT_MAX; for (int k=i+1 ;k<j;++k){ dp[i][j]=min (dp[i][j], dp[i][k] + dp[k][j] + (cuts[j] - cuts[i])); } } } return dp[0 ][m-1 ]; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 func minCost (n int , cuts []int ) int { cuts = append (cuts, 0 ) cuts = append (cuts, n) sort.Ints(cuts) m := len (cuts) dp := make ([][]int , m) for i := range dp { dp[i] = make ([]int , m) } for length := 2 ; length < m; length++ { for i := 0 ; i < m-length; i++ { j := i + length dp[i][j] = math.MaxInt32 for k := i + 1 ; k < j; k++ { dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + (cuts[j] - cuts[i])) } } } return dp[0 ][m-1 ] }
date:2024-11-12 tag:哈希表 动态规划
题解 用哈希表存储字典中的单词,便于查找。 动态规划初始化vectordp(s.size()+1,false),dp[0]=true 遍历字符串s,对于一个位置i
,遍历不大于i
的j
,看是否存在dp[j]
且在哈希表中找到set[s[j:i]]
存在,将位置i
为true,退出子循环。set.count(s.substr(j,i-j))
结果为dp[n]
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution {public : bool wordBreak (string s, vector<string>& wordDict) { unordered_set<string> set (wordDict.begin(),wordDict.end()) ; int n=s.size (); vector<bool >dp (n+1 ,false ); dp[0 ]=true ; for (int i=1 ;i<=n;++i){ for (int j=0 ;j<i;++j){ if (dp[j]&&set.count (s.substr (j,i-j))){ dp[i]=true ; break ; } } } return dp[n]; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 func wordBreak (s string , wordDict []string ) bool { set:=make (map [string ]bool ) for _,val:=range wordDict{ set[val]=true } n:=len (s) dp:=make ([]bool ,n+1 ) dp[0 ]=true for i:=1 ;i<=n;i++{ for j:=0 ;j<i;j++{ if dp[j]&&set[s[j:i]]{ dp[i]=true break } } } return dp[n] }
date:2024-11-13
题解 用大小为2的数组存放当前字符串中0和1的数量,遍历字符串,用数组存放子字符串的0和1数目,每次更新判断是否超过k,退出循环。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution {public : int countKConstraintSubstrings (string s, int k) { int n=s.size (); int res=0 ; for (int i=0 ;i<n;++i){ int count[2 ]={0 }; for (int j=i;j<n;++j){ count[s[j]-'0' ]++; if (count[0 ]>k&&count[1 ]>k){ break ; } res++; } } return res; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 func countKConstraintSubstrings (s string , k int ) int { n:=len (s) res:=0 for i:=0 ;i<n;i++{ count:=[2 ]int {} for j:=i;j<n;j++{ count[s[j]-'0' ]++ if count[0 ]>k&&count[1 ]>k{ break } res++ } } return res }
date:2024-11-14 tag:哈希表
题解 用hashMap解题,对每个字符串,将排序好的字符串作为key
,排序后和key
相同的字符串作为val
. 然后遍历hashmap的key,将哈希表的所有val加入到字符串数组result
中。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution {public : vector<vector<string>> groupAnagrams (vector<string>& strs) { map<string,vector<string>>hashMap; for (auto str:strs){ string temp=str; sort (temp.begin (),temp.end ()); hashMap[temp].push_back (str); } vector<vector<string>>result; for (auto sortMap:hashMap){ result.push_back (sortMap.second); } return result; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 func groupAnagrams (strs []string ) [][]string { hashMap:=make (map [string ][]string ) for _,str:=range strs{ chars:=strings.Split(str,"" ) sort.Strings(chars) key:=strings.Join(chars,"" ) hashMap[key]=append (hashMap[key],str) } result:=make ([][]string ,0 ,len (hashMap)) for _,val:=range hashMap{ result=append (result,val) } return result }
date:2024-11-15 tag:数组
题解 对于每一行 row,计算这一行变成回文最少需要翻转多少次。 对于行,计算grid[i][j]!=grid[i][n-1-j]
的次数。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution {public : int minFlips (vector<vector<int >>& grid) { int m=grid.size (),n=grid[0 ].size (); int countRow=0 ,countVol=0 ; for (int i=0 ;i<m;++i){ for (int j=0 ;j<n/2 ;j++){ countRow+=grid[i][j]!=grid[i][n-1 -j]; } } for (int j=0 ;j<n;j++){ for (int i=0 ;i<m/2 ;i++){ countVol+=grid[i][j]!=grid[m - 1 - i][j]; } } return min (countRow,countVol); } };
date:2024-11-16 tag:数组
题解 见代码
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 class Solution {public : int minFlips (vector<vector<int >>& grid) { int m = grid.size (), n = grid[0 ].size (); int ans = 0 ; for (int i = 0 ; i < m / 2 ; ++i) { for (int j = 0 ; j < n / 2 ; ++j) { int cnt1 = grid[i][j] + grid[i][n - 1 - j] + grid[m - 1 - i][j] + grid[m - 1 - i][n - 1 - j]; ans += min (cnt1, 4 - cnt1); } } if (m % 2 && n % 2 ) { ans += grid[m / 2 ][n / 2 ]; } int diff = 0 , cnt1 = 0 ; if (m % 2 ) { for (int j = 0 ; j < n / 2 ; ++j) { int left = grid[m / 2 ][j]; int right = grid[m / 2 ][n - 1 - j]; if (left != right) { diff++; } else { cnt1 += left * 2 ; } } } if (n % 2 ) { for (int i = 0 ; i < m / 2 ; ++i) { int top = grid[i][n / 2 ]; int bottom = grid[m - 1 - i][n / 2 ]; if (top != bottom) { diff++; } else { cnt1 += top * 2 ; } } } return ans + (diff > 0 ? diff : cnt1 % 4 ); } };
date:2024-11-17 tag:双指针
题解 题目的三个条件可以看成:
不向小于15岁的发
不向年龄小于自己的发 将ages数组排序,定义x,y为互发请求的范围。 x为第一个>=15的排序ages下标 y为第一个大于当前遍历数age的下标
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution {public : int numFriendRequests (vector<int >& ages) { int res=0 ; int x=0 ,y=0 ,n=ages.size (); sort (ages.begin (),ages.end ()); for (auto age:ages){ if (age<=14 ){ continue ; } while (ages[x]<=0.5 *age+7 ){ x++; } while (y+1 <n&&ages[y+1 ]<=age){ y++; } res+=y-x; } return res; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 func numFriendRequests (ages []int ) int { x,y,n:=0 ,0 ,len (ages) res:=0 sort.Ints(ages) for _,age:=range ages{ if age<=14 { continue } for ages[x]*2 <=age+14 { x++ } for y+1 <n&&age>=ages[y+1 ]{ y++ } res+=y-x } return res }
date:2024-11-18 tag:数组
题解 用一个二维数组dirs来存放一个点位可以移动的位置,cnt表示四周元素的个数,sum表示四周元素的和 遍历img数组,对于一个位置img[i][j]
遍历dirs数组看四周的数是否存在。增加cnt的值,修改sum的值 修改res[i][j]
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution {public : vector<vector<int >> imageSmoother (vector<vector<int >>& img) { int m = img.size (), n = img[0 ].size (); vector<vector<int >> dirs{{1 , 0 }, {-1 , 0 }, {0 , -1 }, {0 , 1 }, {-1 , -1 }, {1 , -1 }, {-1 , 1 }, {1 , 1 }}; vector<vector<int >> res (m, vector <int >(n)); for (int i = 0 ; i < m; ++i) { for (int j = 0 ; j < n; ++j) { int cnt = 1 , sum = img[i][j]; for (auto dir : dirs) { int x = i + dir[0 ]; int y = j + dir[1 ]; if (x < m && x >= 0 && y < n && y >= 0 ) { cnt++; sum += img[x][y]; } } res[i][j] = sum / cnt; } } return res; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 func imageSmoother (img [][]int ) [][]int { m, n := len (img), len (img[0 ]) dirs := [][]int {{1 , 0 }, {-1 , 0 }, {0 , -1 }, {0 , 1 }, {-1 , -1 }, {1 , -1 }, {1 , 1 }, {-1 , 1 }} res := make ([][]int , m) for i := range res { res[i] = make ([]int , n) } for i := 0 ; i < m; i++ { for j := 0 ; j < n; j++ { cnt, sum := 1 , img[i][j] for _, dir := range dirs { x, y := i+dir[0 ], j+dir[1 ] if x >= 0 && x < m && y >= 0 && y < n { cnt++ sum += img[x][y] } } res[i][j] = sum / cnt } } return res }
date:2024-11-19 tag:bfs
题解 初始化邻接表,每次增加道路时,需要加入到邻接表中。 遍历道路,每次增加道路,将道路加入到邻接表中。 广度优先搜索邻接表,找出到达n-1的距离
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Solution {public : vector<int > shortestDistanceAfterQueries (int n, vector<vector<int >>& queries) { vector<vector<int >> neighbors (n); for (int i = 0 ; i < n - 1 ; ++i) { neighbors[i].push_back (i + 1 ); } vector<int >res; for (auto querie:queries){ neighbors[querie[0 ]].push_back (querie[1 ]); res.push_back (bfs (n,neighbors)); } return res; } int bfs (int n,const vector<vector<int >>&neighbors) { vector<bool >visited (n,false ); visited[0 ]=true ; queue<pair<int ,int >>q; q.push ({0 ,0 }); while (!q.empty ()){ auto [node,distance]=q.front (); q.pop (); if (node==n-1 ){ return distance; } for (int neighbor:neighbors[node]){ if (!visited[neighbor]){ visited[neighbor]=true ; q.push ({neighbor,distance+1 }); } } } return -1 ; } };
date:2024-11-20 tag:双指针
题解 使用left
,right
表示位置,初始化分别为0
和len(height)
,maxLeft
, maxRight
表示目前位置 当两个指针未相遇时,每次更新maxLeft
和maxRigh
. 当height[left]<height[right]
时必有maxLeft<maxRight
maxLeft-height[left]
表示当前格子接到的雨水。 同理maxRight-height[right]
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution {public : int trap (vector<int >& height) { int left=0 ,right=height.size ()-1 ; int maxLeft=0 ,maxRight=0 ; int res=0 ; while (left<right){ maxLeft=max (maxLeft,height[left]); maxRight=max (maxRight,height[right]); if (height[left]<height[right]){ res+=maxLeft-height[left]; left++; }else { res+=maxRight-height[right]; right--; } } return res; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 func trap (height []int ) int { res:=0 left,right:=0 ,len (height)-1 maxLeft,maxRight:=0 ,0 for left<right{ maxLeft=max(maxLeft,height[left]) maxRight=max(maxRight,height[right]) if height[left]<height[right]{ res+=maxLeft-height[left] left++ }else { res+=maxRight-height[right] right-- } } return res } func max (a,b int ) int { if a>b{ return a }else { return b } }
date:2024-11-21 tag:
题解 无
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution {public : int finalPositionOfSnake (int n, vector<string>& commands) { int x=0 ,y=0 ; for (const auto &command:commands){ switch (command[0 ]){ case 'U' :x--;break ; case 'D' :x++;break ; case 'L' :y--;break ; case 'R' :y++;break ; } } return x*n+y; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 func finalPositionOfSnake (n int , commands []string ) int { x,y:=0 ,0 for _,command:=range commands{ switch command{ case "UP" : x-- case "DOWN" : x++ case "RIGHT" : y++ case "LEFT" : y-- } } return x*n+y }
date:2024-11-22
题解 只有两个真因数,且不包括自己,说明只有1和平方数。 [1,$\sqrt{2}$]的范围内遍历所有质数,将平方从[l,r]范围内去除。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution {public : int nonSpecialCount (int l, int r) { int n = sqrt (r); vector<int > v (n + 1 ) ; int res = r - l + 1 ; for (int i = 2 ; i <= n; i++) { if (v[i] == 0 ) { if (i * i >= l && i * i <= r) { res--; } for (int j = i * 2 ; j <= n; j += i) { v[j] = 1 ; } } } return res; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 func nonSpecialCount (l int , r int ) int { n:=int (math.Sqrt(float64 (r))) res:=r-l+1 v:=make ([]int ,n+1 ) for i:=2 ;i<=n;i++{ if v[i]==0 { if i*i>=l&&i*i<=r{ res-- } for j:=i*2 ;j<=n;j+=i{ v[j]=1 } } } return res }