NO.3无重复的最长子串
思路:一个数组保存a-z上一个出现字母的位置,一旦出现重复回到上次出现后一个位置。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s=="")return 0;
else if(s==" ")return 1;
int length =0;
int A[130]={0};
int count =0;
for(int i=0;i<s.size();i++){
if(A[s[i]]==0){
A[s[i]]=i+1;
count++;
}else{
length = max(length,count);
i=A[s[i]]-1;
memset(A,0,130*sizeof(int));
count=0;
}
}
length=max(length,count);
return length;
}
};
NO4.寻找两个有序数组的中位数
要求:时间复杂度为O(m+n)
思路:合并两个有序有数组,取新数组的中间数。
技术点:①合并有序数组;②为数字分配空间
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int len1 = nums1.size();
int len2 = nums2.size();
int n1=0,n2=0,n=0;
int len = len1+len2;
int *merge;
merge = (int *)malloc(len*sizeof(int));
while(n1<len1||n2<len2){
if(n1>=len1)merge[n++]=nums2[n2++];
else if(n2>=len2)merge[n++] = nums1[n1++];
else{
if(nums1[n1]>=nums2[n2])
merge[n++]=nums2[n2++];
else
merge[n++]=nums1[n1++];
}
}
double ans;
int t = len/2;
if(len%2==0){
ans = (merge[t-1]+merge[t])/2.0;
}else{
ans = (double)merge[t];
}
return ans;
}
};
NO.7整数反转
解题关键点及Tip:
①注意有无溢出,不止是结果的溢出,在计算的过程中也会出现溢出,所以中间的计算要用long型,得出结果后再判断是否溢出。
②可用十六进制表示很大的数。如0x7fffffff
class Solution {
public:
int reverse(int x) {
int num[33]={0};
int len=0,flag=0;
long sum=0;
int max = 0x7fffffff,min = 0x80000000;
if(x<0) {
flag=1;
}
while(x!=0){
sum=sum*10+x%10;
x/=10;
}
if(sum>max||sum<min)return 0;
if(flag==1 && sum>0){
return -sum;
}else{
return sum;
}
}
};
NO.9回文数
①因为可能有溢出,所以改为long long型
class Solution {
public:
bool isPalindrome(int x) {
if(x<0)return false;
else if(x==0) return true;
else{
long long sum=0,c=x;
while(x!=0){
sum=sum*10+x%10;
x/=10;
}
if(sum==c)
return true;
else return false;
}
}
};
NO.11盛最多水的容器
思路:从最宽的开始,两个指针一个指向最左,一个指向最右,宽度越宽面积大概率会较大,但是高度也会影响,将高度较小的那个往里缩,缩进后进行判断那个面积更大。
class Solution {
public:
int maxArea(vector<int>& height) {
int i=0,j=height.size()-1;
int h;
int area =0;
while(i<j){
h = min(height[i],height[j]);
area = max(area,h*(j-i));
if(height[i]>height[j])j--;
else i++;
}
return area;
}
};
NO.14最长公共前缀
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if(strs.size()==0)return "";
string str1 = strs[0];
int length =str1.size();
int xlen = str1.size();
string prefix = "";
int j;
for(int i=0;i<strs.size();i++){
string temp = strs[i];
int templen = temp.size();
int len=min(xlen,templen);
for(j=0;j<len;j++){
if(temp[j]!=str1[j]){
break;
}
}
length = min(length,j);
}
if(length==0)return "";
else{
prefix = str1.substr(0,length);
return prefix;
}
}
};
NO.15三数之和
①排序,sort(vector.begin(),vector.end());②考虑去除重复
NO.20有效的括号
①使用栈,stack<char> a;
class Solution {
public:
bool isValid(string s) {
stack<char> a;
if(s=="")return true;
a.push(s[0]);
for(int i=1;i<s.length();i++){
switch(s[i]){
case '(':
case '[':
case '{':
a.push(s[i]);
break;
case ']':
if((!a.empty())&&a.top()=='[')a.pop();
else a.push(s[i]);
break;
case ')':
if((!a.empty())&&a.top()=='(')a.pop();
else a.push(s[i]);
break;
case '}':
if((!a.empty())&&a.top()=='{')a.pop();
else a.push(s[i]);
break;
}
}
if(a.empty())return true;
else return false;
}
};
NO.17电话号码的字母组合
class Solution {
public:
map<char,string> mp = {{'2',"abc"},{'3',"def"},{'4',"ghi"},{'5',"jkl"}, {'6',"mno"},{'7',"pqrs"},{'8',"tuv"},{'9',"wxyz"}};
vector<string> res;
string cur;
vector<string> letterCombinations(string digits) {
if(digits=="")return res;
DFS(digits);
return res;
}
void DFS(string digit){
if(digit=="")res.push_back(cur);
else{
char num = digit[0];
string letter = mp[num];
for(int i=0;i<letter.size();i++){
cur.push_back(letter[i]);
DFS(digit.substr(1));
cur.pop_back();
}
}
}
};
NO26.删除排序数组中的重复项
①两个指针,从前往后判断,如果后一个与当前相同,后指针不断往后移;遇到不同值时,将后指针的值覆盖前指针的下一个值,前指正++
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()<2)return nums.size();
int j=0;
for(int i=1;i<nums.size();i++){
if(nums[j]!=nums[i]){
nums[++j]=nums[i];
}
}
return ++j;
}
};
NO.27移除元素
Question:为什么vector的remove用不了?
暂时使用双指针。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int j=0;
for(int i=0;i<nums.size();i++){
if(nums[i]!=val){
nums[j]=nums[i];
j++;
}
}
return j;
}
};
NO28.实现strStr()
思路:主要用到了string的find函数,如果找不到,函数会返回:string::npos
class Solution {
public:
int strStr(string haystack, string needle) {
if(needle=="")return 0;
if(haystack=="" || haystack.size()<needle.size())return -1;
int res = haystack.find(needle);
if(res==string::npos)return -1;
else return res;
}
};
NO35.搜索插入位置
没有用二分查找,直接一遍迭代过去了。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int n= nums.size();
for(int i=0;i<n;i++){
if(nums[i]>=target)return i;
}
return n;
}
};
NO53.求最大子序列和
①:分治法
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.size()==0)return 0;
return func(nums,0,nums.size()-1);
}
int func(vector<int>&nums , int l, int r){
if(l==r)return nums[l];
int mid = (l+r)/2;
int left = func(nums,l,mid);
int right = func(nums,mid+1,r);
int sum=0;
int tr=0x80000000,tl=0x80000000;
for(int i=mid+1;i<=r;i++){
sum+=nums[i];
if(sum>tr)tr=sum;
}
sum=0;
for(int i=mid;i>=l;i--){
sum+=nums[i];
if(sum>tl)tl=sum;
}
sum = tl+tr;
int m = max(left,right);
return max(m,sum);
}
};
NO55.跳跃游戏
①先用了递归,试了几个测试用例都通过了,但是超时orz
class Solution {
public:
bool canJump(vector<int>& nums) {
int n = nums.size();
if(n==1)return true;
if(digui(nums,0,n-1))return true;
return false;
}
bool digui(vector<int>& nums,int curPosition,int n){
if(curPosition==n)return true;
for(int i=1;i<=nums[curPosition];i++){
if(digui(nums,curPosition+i,n))return true;
else continue;
}
return false;
}
};
②看了评论的思路:
从后往前找,如果发现nums[i]=0,则从i往前找,是否有nums[j]>i-j,有则可以跳过这个0,无则return false。
class Solution {
public:
bool canJump(vector<int>& nums) {
int n = nums.size();
if(n==1)return true;
for(int i=n-2;i>=0;i--){
if(nums[i]==0){
int flag = 0;
for(int j=i-1;j>=0;j--){
if(nums[j]>i-j){
i=j;
flag=1;
break;
}
}
if(flag==0)return false;
}
}
return true;
}
};
NO66.加一
注意vector的插入和删除方法。
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
int n = digits.size();
digits[n-1]+=1;
int d=0;
for(int i=n-1;i>=0;i--){
int temp = digits[i]+d;
if(temp>=10){
digits[i]=temp-10;
d=1;
}else{
digits[i]=temp;
d=0;
}
}
if(d==1)digits.insert(digits.begin(),1);
return digits;
}
};
NO83.删除排序链表中的重复元素
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head==NULL) return head;
ListNode * last = head;
ListNode * p = head->next;
while(p){
if(p->val==last->val){
p=p->next;
last->next = p;
}else{
p=p->next;
last = last->next;
}
}
return head;
}
};
NO94.二叉树的中序遍历
Note:vector的插入,push_back(element);
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ans;
travers(root,ans);
return ans;
}
void travers(TreeNode* t,vector<int> & a){
if(t==NULL)return;
travers(t->left,a);
a.push_back(t->val);
travers(t->right,a);
}
};
NO98.验证二叉搜索树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int flag = 0;
bool isValidBST(TreeNode* root) {
if(root==NULL)return true;
int min = getMin(root);
min = (min==0x80000000)?min:(min-1);
return judge(root,min);
}
int getMin(TreeNode* root){
if(root->left==NULL)return root->val;
return getMin(root->left);
}
bool judge(TreeNode* root,int & max){
if(root==NULL)return true;
bool left = judge(root->left,max);
if(left){
if(flag==0){
flag=1;
}else if(root->val<=max){
return false;
}
max = root->val;
return judge(root->right,max);
}else return false;
}
};
NO100.相同的树
思路:递归判断
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
if(p==NULL && q==NULL)return true;
if(p==NULL || q==NULL)return false;
if(p->val == q->val){
bool left = isSameTree(p->left,q->left);
bool right = isSameTree(p->right,q->right);
return left&right;
}else return false;
}
};
NO101.对称二叉树
思路:同上,递归判断
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(root==NULL)return true;
return iss(root->left,root->right);
}
bool iss(TreeNode* l,TreeNode* r){
if(l==NULL && r==NULL)return true;
if(l==NULL || r==NULL)return false;
if(l->val != r->val) return false;
bool s1 = iss(l->left,r->right);
bool s2 = iss(l->right,r->left);
return s1 & s2;
}
};
NO104.二叉树的最大深度
Note:递归
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root==NULL)return 0;
else {
int left = maxDepth(root->left)+1;
int right = maxDepth(root->right)+1;
return max(left,right);
}
}
};
NO108.将有序数组转换为二叉树
思路:从中间开始二分
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
return fun(nums,0,nums.size()-1);
}
TreeNode* fun(vector<int> & nums,int l , int r){
if(l>r)return NULL;
int mid=(l+r)/2;
TreeNode * root = new TreeNode(nums[mid]);
root->left = fun(nums,l,mid-1);
root->right = fun(nums,mid+1,r);
return root;
}
};
NO111.二叉树的最小深度
class Solution {
public:
int minDepth(TreeNode* root) {
if(root==NULL){
return 0;
}
int left = minDepth(root->left);
int right = minDepth(root->right);
int ans;
if(left&&right)ans = 1+min(left,right);
else ans = 1+left+right;
return ans;
}
};
NO169.求众数
思路:①排序后返回中间的位置即可。②注意sort函数用法
ps:没有懂那个位运算法
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(),nums.end());
return nums[nums.size()/2];
}
};
NO136.只出现一次的数字
思想:a^a=0,0^a=a,所以因为其他数都出现两次,所以其他的结果都为0,留下的一个为只出现一次。
class Solution {
public:
int singleNumber(vector<int>& nums) {
int res = 0;
for(int i=0;i<nums.size();i++){
res = res^nums[i];
}
return res;
}
};
NO841.钥匙和房间
思路:使用dfs算法
class Solution {
public:
int a[1000];
bool canVisitAllRooms(vector<vector<int>>& rooms) {
int n = rooms.size();
memset(a,0,n*sizeof(int));
dfs(0,rooms);
for(int i=0;i<n;i++){
if(a[i]==0)return false;
}
return true;
}
void dfs(int x,vector<vector<int>> & rooms){
a[x]++;
vector<int> keys = rooms[x];
int n=keys.size();
int key=0;
for(int i=0;i<n;i++){
key = keys[i];
if(a[key]==0){
dfs(key,rooms);
}
}
}
};
NO938.二叉搜索树的范围和
思路:①首先注意到二叉搜索树的兴致,左和右之间的所有节点即为L<=X<=R
②递归,遍历每个节点的左子树和右子树,若为空节点,返回0。
return rangeSumBST(root->left,L,R)+rangeSumBST(root->right,L,R);
class Solution {
public:
int rangeSumBST(TreeNode* root, int L, int R) {
if(root==NULL)return 0;
int val = root->val;
if(val>=L && val<= R)return rangeSumBST(root->left,L,R)+rangeSumBST(root->right,L,R)+val;
else return rangeSumBST(root->left,L,R)+rangeSumBST(root->right,L,R);
}
};
NO1137.第n个泰波那契书
思路:递归return f(n-3)+f(n-2)+f(n-1);
NOTE:纯用递归会超时,所以建立一个数组,每算得一个f(n)可以存入数组中,这样后续可直接调用数组。
class Solution {
public:
int A[40]={0,1,1};
int tribonacci(int n) {
if(n==0)return 0;
else if(A[n]) return A[n];
else{
int ans = (tribonacci(n-3)+tribonacci(n-2)+tribonacci(n-1));
A[n]=ans;
return ans;
};
}
};