Leetcode 算法入门(C++) 每题第一个代码均为本人所写代码,并非最优解,部分解法参考题解。
第 1 天 二分查找 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution {public : int search (vector<int >& nums, int target) { int l = 0 , r = nums.size ()-1 ; while (l <= r) { int m = (l + r) / 2 ; if (target == nums[m]) { return m; } else if (target < nums[m]) { r = m - 1 ; } else { l = m + 1 ; } } return -1 ; } };
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution {public : int firstBadVersion (int n) { long long int l=1 ,r=n,ans=0 ; while (l<=r) { long long int m=(l+r)/2 ; if (isBadVersion (m)) { ans=m; r=m-1 ; } else { l=m+1 ; } } return ans; } };
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
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 class Solution {public : int searchInsert (vector<int >& nums, int target) { int l=0 ,r=nums.size ()-1 ,m; while (l<=r) { m=(l+r)/2 ; if (nums[m]==target) { return m; } else if (nums[m]>target) { r=m-1 ; } else { l=m+1 ; } } if (target>nums[m]) return m+1 ; else return m; } };
第 2 天 双指针 977. 有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
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 > sortedSquares (vector<int >& nums) { int r=nums.size ()-1 ; vector<int > result (nums.size(),0 ) ; for (int i=0 ,j=r;i<=j; ) { if (nums[i]*nums[i]<nums[j]*nums[j]) { result[r] = nums[j]*nums[j]; j--; } else { result[r] = nums[i]*nums[i]; i++; } r--; } return result; } };
给你一个数组,将数组中的元素向右轮转 k
个位置,其中 k
是非负数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution {public : void reverse (vector<int >& A,int i,int j) { while (i<j) { int temp = A[j]; A[j]=A[i]; A[i]=temp; i++; j--; } } void rotate (vector<int >& nums, int k) { k=k%nums.size (); int r=nums.size ()-1 ; reverse (nums,0 ,r); reverse (nums,0 ,k-1 ); reverse (nums,k,r); } };
时间复杂度$O(n)$
空间复杂度$O(1)$
数组,数学,双指针
第 3 天 双指针 给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
class Solution {public : void moveZeroes (vector<int >& nums) { int len=nums.size (); int j=0 ; for (int i=0 ;i<len;i++) { if (nums[i]!=0 ) nums[j++]=nums[i]; } while (j<len) { nums[j++]=0 ; } } };
时间复杂度$O(n)$
空间复杂度$O(1)$
数组
给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution {public : vector<int > twoSum (vector<int >& numbers, int target) { int i=0 ,j=numbers.size ()-1 ; bool k=0 ; while (i<j) { if (target==numbers[i]+numbers[j]) { break ; } else if (target<numbers[i]+numbers[j]) { j--; } else { i++; } } return {i+1 ,j+1 }; } };
时间复杂度$O(n)$
空间复杂度$O(1)$
数组,指针,二分查找
第 4 天 双指针 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
class Solution {public : void reverseString (vector<char >& s) { int i=0 ,j=s.size ()-1 ; for (;i<j;i++,j--) { char temp=s[i]; s[i]=s[j]; s[j]=temp; } } };
时间复杂度$O(n)$
空间复杂度$O(1)$
双指针,字符串
给定一个字符串 s
,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
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 class Solution {public : void reverseString (string& s,int l,int r) { int i=l,j=r; for (;i<j;i++,j--) { char temp=s[i]; s[i]=s[j]; s[j]=temp; } } string reverseWords (string s) { int l=0 ,r=0 ; int len=s.length (); for (int k=0 ;k<=len;k++) { if (s[k]==' ' ||k==len) { r=k-1 ; reverseString (s,l,r); l=k+1 ; } } return s; } };
时间复杂度$O(n)$
空间复杂度$O(1)$
双指针,字符串
第 5 天 双指针 给定一个头结点为 head
的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
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 class Solution {public : ListNode* middleNode (ListNode* head) { int i=1 ; ListNode *now=head; while (now->next) { now=now->next; ListNode *temp=now; bool flag=0 ; for (int j=0 ;j<=i;j++) { temp=temp->next; if (temp==nullptr ) { flag=1 ; break ; } } if (flag==1 ) { break ; } i++; } return now; } };
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 class Solution {public : ListNode* removeNthFromEnd (ListNode* head, int n) { ListNode *slow=head,*fast=head; for (int i=0 ;i<n;i++) { fast=fast->next; } if (fast==nullptr ) { head=head->next; } while (fast!=nullptr &&fast->next!=nullptr ) { slow=slow->next; fast=fast->next; } if (slow->next!=nullptr ) slow->next=slow->next->next; else slow->next=nullptr ; return head; } };
第 6 天 滑动窗口 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 class Solution {public : int lengthOfLongestSubstring (string s) { int len=s.length (); map<char ,int > h; int ans=0 ,l=0 ,r=0 ; for (int i=0 ;i<len;i++) { if (h.find (s[i])==h.end ()) { h[s[i]]=i; } else { l=max (h[s[i]]+1 ,l); h[s[i]]=i; } r=i; if (r-l+1 >ans) ans=r-l+1 ; } return ans; } };
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 : bool checkInclusion (string s1, string s2) { int len1=s1.length (),len2=s2.length (); if (len1>len2) return false ; int windowSize=len1; vector<int > vec1 (26 ,0 ) ; vector<int > vecWin (26 ,0 ) ; for (int i=0 ;i<windowSize;i++) { vec1[s1[i]-'a' ]++; vecWin[s2[i]-'a' ]++; } for (int i=windowSize-1 ;i<len2;i++) { if (vec1==vecWin) return true ; vecWin[s2[i+1 -windowSize]-'a' ]--; if (i<len2-1 ) vecWin[s2[i+1 ]-'a' ]++;; } return false ; } };
第 7 天 广度优先搜索 / 深度优先搜索 有一幅以 m x n 的二维整数数组表示的图画 image ,其中 image[i][j] 表示该图画的像素值大小。
你也被给予三个整数 sr , sc 和 newColor 。你应该从像素 image[sr][sc] 开始对图像进行 上色填充 。
为了完成 上色工作 ,从初始像素开始,记录初始坐标的 上下左右四个方向上 像素值与初始坐标相同的相连像素点,接着再记录这四个方向上符合条件的像素点与他们对应 四个方向上 像素值与初始坐标相同的相连像素点,……,重复该过程。将所有有记录的像素点的颜色值改为 newColor 。
最后返回 经过上色渲染后的图像 。
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 : void dfs (vector<vector<int >>& image, int sr, int sc, int newColor,unordered_map<int ,int > vis) { vis[sr*50 +sc]=1 ; int mx[4 ]={1 ,-1 ,0 ,0 },my[4 ]={0 ,0 ,1 ,-1 }; for (int i=0 ;i<4 ;i++) { int x1=sr+mx[i],y1=sc+my[i]; if (x1>=0 &&x1<image.size ()&&y1>=0 &&y1<image[sr].size ()&&vis[x1*50 +y1]==0 &&image[sr][sc]==image[x1][y1]) { dfs (image,sr+mx[i],sc+my[i],newColor,vis); } } if (image[sr][sc]!=newColor) image[sr][sc]=newColor; } vector<vector<int >> floodFill (vector<vector<int >>& image, int sr, int sc, int newColor) { unordered_map<int ,int > vis; dfs (image,sr,sc,newColor,vis); return image; } };
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 class Solution {public : int dfs (vector<vector<int >>& grid,int x,int y,int count) { if (x<0 ||x>=grid.size ()||y<0 ||y>=grid[0 ].size ()||grid[x][y]==0 ) return count; else { grid[x][y]=0 ; count++; count=max (count,dfs (grid,x+1 ,y,count)); count=max (count,dfs (grid,x-1 ,y,count)); count=max (count,dfs (grid,x,y-1 ,count)); count=max (count,dfs (grid,x,y+1 ,count)); return count; } } int maxAreaOfIsland (vector<vector<int >>& grid) { int ans=0 ; for (int i=0 ;i<grid.size ();i++) for (int j=0 ;j<grid[0 ].size ();j++) { if (grid[i][j]) ans=max (ans,dfs (grid,i,j,0 )); } return ans; } };
第 8 天 广度优先搜索 / 深度优先搜索 给你两棵二叉树: root1 和 root2 。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意: 合并过程必须从两个树的根节点开始。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution {public : TreeNode* mergeTrees (TreeNode* root1, TreeNode* root2) { if (root1==nullptr ) return root2; if (root2==nullptr ) return root1; root1->val+=root2->val; root1->left=mergeTrees (root1->left,root2->left); root1->right=mergeTrees (root1->right,root2->right); return root1; } };
时间复杂度: $O(max(n1,n2)),n1、n2分别为树的结点个数$
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node { int val; Node left; Node right; Node *next; } 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
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 Solution {public : Node* connect (Node* root) { queue<Node*> now; now.push (root); Node* p=NULL ; while (!now.empty ()) { queue<Node*> nextLay; Node* temp=NULL ; while (!now.empty ()) { p=now.front (); now.pop (); if (p) { if (p->left) nextLay.push (p->left); if (p->right) nextLay.push (p->right); } if (temp) { temp->next=p; } temp=p; } if (p) p->next=NULL ; now=nextLay; } return root; } };
第 9 天 广度优先搜索 / 深度优先搜索 给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。
两个相邻元素间的距离为 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 37 38 39 40 41 42 class Solution {public : vector<vector<int >> updateMatrix (vector<vector<int >>& mat) { int row_size=mat.size (); int col_size=mat[0 ].size (); queue<pair<int ,int >> q; for (int i=0 ;i<row_size;i++) { for (int j=0 ;j<col_size;j++) { if (mat[i][j]==0 ) { q.emplace (i,j); } else { mat[i][j]=-1 ; } } } int dx[4 ]={-1 ,1 ,0 ,0 },dy[4 ]={0 ,0 ,-1 ,1 }; while (!q.empty ()) { auto [x,y]=q.front (); q.pop (); for (int i=0 ;i<4 ;i++) { int newx=x+dx[i]; int newy=y+dy[i]; if (newx>=0 &&newx<row_size&&newy>=0 &&newy<col_size&&mat[newx][newy]==-1 ) { mat[newx][newy]=mat[x][y]+1 ; q.emplace (newx,newy); } } } return mat; } };
在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一:
值 0 代表空单元格; 值 1 代表新鲜橘子; 值 2 代表腐烂的橘子。 每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。
返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 class Solution {public : int orangesRotting (vector<vector<int >>& grid) { int row_size=grid.size (); int col_size=grid[0 ].size (); queue<pair<int ,int >> q; int t[row_size][col_size]; memset (t,0 ,sizeof (t)); for (int i=0 ;i<row_size;i++) { for (int j=0 ;j<col_size;j++) { if (grid[i][j]==2 ) { q.emplace (i,j); t[i][j]=0 ; } } } int ans=0 ; int dx[4 ]={-1 ,1 ,0 ,0 },dy[4 ]={0 ,0 ,-1 ,1 }; while (!q.empty ()) { auto [x,y]=q.front (); q.pop (); for (int i=0 ;i<4 ;i++) { int newx=x+dx[i]; int newy=y+dy[i]; if (newx>=0 &&newx<row_size&&newy>=0 &&newy<col_size&&grid[newx][newy]==1 ) { grid[newx][newy]=2 ; t[newx][newy]=t[x][y]+1 ; ans=max (ans,t[newx][newy]); q.emplace (newx,newy); } } } for (int i=0 ;i<row_size;i++) { for (int j=0 ;j<col_size;j++) { if (grid[i][j]==1 ) return -1 ; } } return ans; } };
第 10 天 递归 / 回溯 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
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 : ListNode* mergeTwoLists (ListNode* list1, ListNode* list2) { if (list1==NULL ) return list2; if (list2==NULL ) return list1; if (list1->val<list2->val) { list1->next=mergeTwoLists (list1->next,list2); return list1; } else { list2->next=mergeTwoLists (list1,list2->next); return list2; } } };
时间复杂度:O(n+m),其中n、m分别为两链表长度
递归,链表
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
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 class Solution {public : ListNode* reverseList (ListNode* head) { ListNode* res=NULL ; ListNode* cur=head; while (cur!=NULL ) { ListNode* temp=cur; cur=cur->next; temp->next=res; res=temp; } return res; } };
第 11 天 递归 / 回溯 给定两个整数 n
和 k
,返回范围 [1, n]
中所有可能的 k
个数的组合。
你可以按 任何顺序 返回答案。
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 class Solution {public : vector<vector<int >> ans; int num_max,len_max; void addNumber (vector<int > vec,int num) { vec.push_back (num); if (vec.size ()==len_max) ans.push_back (vec); else if (num<num_max&&num_max-num>=len_max-vec.size ()) { for (int i=num+1 ;i<=num_max;i++) { addNumber (vec,i); } } } vector<vector<int >> combine (int n, int k) { num_max=n; len_max=k; vector<int > vec; for (int i=1 ;i<=num_max-len_max+1 ;i++) addNumber (vec,i); return ans; } };
给定一个不含重复数字的数组 nums
,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
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 class Solution {public : int len_max; vector<vector<int >> ans; unordered_map<int ,int > used; void backtrack (vector<int > vec,vector<int > nums,unordered_map<int ,int > used,int len_max) { if (vec.size ()==len_max) { ans.push_back (vec); return ; } else { for (int i=0 ;i<len_max;i++) { if (used[i]==0 ) { vec.push_back (nums[i]); used[i]=1 ; backtrack (vec,nums,used,len_max); used[i]=0 ; vec.pop_back (); } } } } vector<vector<int >> permute (vector<int >& nums) { len_max=nums.size (); vector<int > vec; backtrack (vec,nums,used,len_max); return ans; } };
给定一个字符串 s
,通过将字符串 s
中的每个字母转变大小写,我们可以获得一个新的字符串。
返回 所有可能得到的字符串集合 。以 任意顺序 返回输出。
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 class Solution {public : vector<string> ans; void backTrack (string S,int i) { if (i==S.size ()) { ans.push_back (S); return ; } if (!isalpha (S[i])) backTrack (S,i+1 ); else { S[i]=tolower (S[i]); backTrack (S,i+1 ); S[i]=toupper (S[i]); backTrack (S,i+1 ); } } vector<string> letterCasePermutation (string s) { backTrack (s,0 ); return ans; } };
第 12 天 动态规划 假设你正在爬楼梯。需要 n
阶你才能到达楼顶。
每次你可以爬 1
或 2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution {public : int climbStairs (int n) { if (n<=2 ) return n; int dp[2 ]; dp[0 ]=1 ; dp[1 ]=2 ; for (int i=3 ;i<=n;i++) { int sum=dp[0 ]+dp[1 ]; dp[0 ]=dp[1 ]; dp[1 ]=sum; } return dp[1 ]; } };
时间复杂度O(n),空间复杂度O(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 class Solution {public : int rob (vector<int >& nums) { int ans=0 ; int len=nums.size (); if (len==1 ) { return nums[0 ]; } if (len==2 ) { return max (nums[0 ],nums[1 ]); } int dp[3 ]; dp[0 ]=nums[0 ]; dp[1 ]=nums[1 ]; dp[2 ]=nums[0 ]+nums[2 ]; for (int i=3 ;i<len;i++) { int temp0=dp[1 ]; int temp1=dp[2 ]; dp[2 ]=max (max (dp[0 ],dp[1 ])+nums[i],dp[2 ]); dp[0 ]=temp0; dp[1 ]=temp1; } ans=max (max (dp[0 ],dp[1 ]),dp[2 ]); return ans; } };
时间复杂度O(n),空间复杂度O(1)
数组,动态规划
给定一个三角形 triangle ,找出自顶向下的最小路径和。
每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一步可以移动到下一行的下标 i 或 i + 1 。
class Solution {public : int minimumTotal (vector<vector<int >>& triangle) { for (int i=triangle.size ()-2 ;i>=0 ;i--) { for (int j=0 ;j<triangle[i].size ();j++) { triangle[i][j]+=min (triangle[i+1 ][j],triangle[i+1 ][j+1 ]); } } return triangle[0 ][0 ]; } };
时间复杂度O(n),n=triangle.size()
数组,动态规划
第 13 天 位运算 给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回 false 。
如果存在一个整数 x 使得 n == 2^x ,则认为 n 是 2 的幂次方。
class Solution {public : bool isPowerOfTwo (int n) { return n>0 && !(n&(n-1 )); } };
class Solution {public : int hammingWeight (uint32_t n) { int cnt=0 ; while (n) { cnt+=n&1 ; n>>=1 ; } return cnt; } };
第 14 天 位运算 颠倒给定的 32 位无符号整数的二进制位。
class Solution {public : uint32_t reverseBits (uint32_t n) { uint32_t ans=0 ; int t=32 ; while (t--) { ans<<=1 ; ans+=n&1 ; n>>=1 ; } return ans; } };
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
class Solution {public : int singleNumber (vector<int >& nums) { int ans=0 ; for (int i=0 ;i<nums.size ();i++) { ans^=nums[i]; } return ans; } };