【LEETCODE刷题记录】【中等】【共50题】

2. 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

# Definition for singly-linked list.


class Solution:
    # @return a ListNode
    def addTwoNumbers(self, l1, l2):
        if l1 is None:
            return l2
        elif l2 is None:
            return l1
        else:
            carry = 0
            ret = ListNode(0)
            ret_Last = ret
            while(l1 or l2):
                sum = 0
                if l1:
                    sum += l1.val
                    l1 = l1.next
                if l2:
                    sum += l2.val
                    l2 = l2.next
                sum += carry
                ret_Last.next = ListNode(sum % 10)
                ret_Last = ret_Last.next
                carry = (sum >= 10)
            ret = ret.next
            if carry:
                ret_Last.next = ListNode(1)
            del ret_Last
            return ret

3. 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

class Solution:
    #def lengthOfLongestSubstring(self, s: str) -> int:
    def lengthOfLongestSubstring(self, str):
    		retcount=0
    		count=1
    		j=0
    		f=0
    		i=-1
    		t=0
    		if len(str) == 0 or len(str) == 1:
    			retcount=len(str)
    		else:
    			while i < len(str):
    				#print("i=",i)
    				#print("t=",t)
    				if f == 1:
    					i=k+1
    					f=0
    				else:
    					i=i+1
    				#print("i=",i)
    				#temp=str[i]
    				#print("str[i]=",str[i])
    				#print("str[0:i-1]=",str[j:i])  			
    				if i >0 and i<len(str):
    					if str[i] not in str[j:i]:
   							count=count+1
   							#print("count1=",count)       
    					else:
    						if count>retcount:
    							retcount=count
    						count=0
    						for k in range(j,i): 
    							if str[k]==str[i]:
    								#print("k=",k)
    								break
    							#j=i
    						j=k+1   						
    						#print("j=",j)
    						#print("count2=",count)
    						#print("retcount=",retcount)    							
    						f=1
    				t=t+1                          
    			if count>retcount:
    				retcount=count
    		return 	retcount

6. Z 字形变换

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

P   A   H   N
A P L S I I G
Y   I   R

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"

class Solution:
    #def convert(self, s: str, numRows: int) -> str:
    def convert(self, s, numRows):
        if numRows==1 or numRows>=len(s) :return s
        r,j,k=['']*numRows,0,1
        print("r=",r)
        print("j=",j)
        print("k=",k)
        for i in s:
            r[j]+=i
            j=j+k
            if j == numRows-1 or j==0 :
                k=-k 
        return "".join(r)

7. 整数反转

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。

如果反转后整数超过 32 位的有符号整数的范围 [−231,  231 − 1] ,就返回 0。

假设环境不允许存储 64 位整数(有符号或无符号)。

class Solution:
    #def reverse(self, x: int) -> int:
    def reverse(self, x):    
        #print("str=",str(x))
        strx=str(x)
        #print("strx=",strx)
        stry = ""
        #print("stry=",stry)
        i=0;
        #j=0;
        l=len(strx)
        if x<0:
            strx=strx[1:l]
        #print("strx=",strx)
        l=len(strx)
        while i<l:
            stry+=strx[l-i-1]
            i=i+1
        #print("stry=",stry)
        y=int(stry)
        if x<0:
            y=-y
        if y<-2**31 or y>2**31-1:
            y=0
        return y

11. 盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

#class Solution:
    #def maxArea(self, height: List[int]) -> int:7u

class Solution(object):
    def maxArea(self, height):
        l = 0
        r = len(height)-1
        res = 0

        if len(height)== 0 or len(height)== 1:
            return 0

        while l<r:
            if height[l]<height[r]:
                if res<(r-l)*height[l]:
                    res=(r-l)*height[l]
                l=l+1
            else:
                if res<(r-l)*height[r]:
                    res=(r-l)*height[r]
                r=r-1
        return res

        

12. 整数转罗马数字

罗马数字包含以下七种字符: I, V, X, LCD 和 M

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

  • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
  • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
  • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

给你一个整数,将其转为罗马数字。

class Solution:
    #def intToRoman(self, num: int) -> str:
    def intToRoman(self, num) :
        l1=int(num/1000)
        print("l1=",l1)
        m1=num%1000
        print("m1=",m1)
        l2=int(m1/100)
        print("l2=",l2)
        m2=m1%100
        print("m2=",m2)
        l3=int(m2/10)
        print("l3=",l3)
        m3=m2%10
        print("m3=",m3)
        l4=m3
        print("l4=",l4)
        i=0
        stry = ""
        while i<l1:
            stry+="M"
            i=i+1
        print("stry=",stry)

        if l2==9:
            stry+="CM"
        else:
            if l2>=5:
               stry+="D" 
               i=5
               while i<l2:
                   stry+="C"
                   i=i+1
            else:
                if l2==4:
                    stry+="CD"
                else:
                    i=0
                    while i<l2:
                        stry+="C"
                        i=i+1

        print("stry=",stry)

        if l3==9:
            stry+="XC"
        else:
            if l3>=5:
               stry+="L" 
               i=5
               while i<l3:
                   stry+="X"
                   i=i+1
            else:
                if l3==4:
                    stry+="XL"
                else:
                    i=0
                    while i<l3:
                        stry+="X"
                        i=i+1

        print("stry=",stry)

        if l4==9:
            stry+="IX"
        else:
            if l4>=5:
               stry+="V" 
               i=5
               while i<l4:
                   stry+="I"
                   i=i+1
            else:
                if l4==4:
                    stry+="IV"
                else:
                    i=0
                    while i<l4:
                        stry+="I"
                        i=i+1

        print("stry=",stry)

        return stry





    

15. 三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

class Solution:
    #def threeSum(self, nums: List[int]) -> List[List[int]]:
    def threeSum(self, nums: List[int]):
        nums.sort()
        print("nums=",nums)
        list_ret = []
        d = {} 
        for i in range(len(nums)):
            l=i+1
            r=len(nums)-1
            while(l<r):
                s=nums[i]+nums[l]+nums[r]
                if s==0:
                    #list_ret.append[nums[i],nums[l],nums[r]]
                    col = [nums[i],nums[l],nums[r]]
                    maxc=max(col)
                    minc=min(col)
                    if (maxc,minc) not in d:
                        d[(maxc,minc)]=1
                        list_ret.append(col)  
                    #print("col=",col)
                    #print("list_ret=",list_ret)
                    #print("d=",d)
                    r=r-1
                    l=l+1
                else :
                    if s>0:
                        r=r-1
                    else:
                        l=l+1
        return list_ret

16. 最接近的三数之和

给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。

假定每组输入只存在恰好一个解。

class Solution:
    #def threeSumClosest(self, nums: List[int], target: int) -> int:
    def threeSumClosest(self, nums, target):
        nums.sort()
        length=len(nums)
        d=10000
        st=0
        for i in range(len(nums)):
            r=i+1
            l=length-1
            while(r<l):
                s=nums[i]+nums[r]+nums[l]
                #print("nums[i]",nums[i])
                #print("nums[r]",nums[r])
                #print("nums[l]",nums[l])
                #print("s=",s)
                #print("d=",d)
                #print("abs=",abs(s-target))
                if d>abs(s-target):
                    d=abs(s-target)
                    st=s
                if s-target==0:
                    return st
                else:
                    if s-target<0:
                        r=r+1
                    else:
                        l=l-1
        return st    
                
                

33. 搜索旋转排序数组

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

class Solution:
    #def search(self, nums: List[int], target: int) -> int:
    def search(self, nums: List[int], target: int):
        lens=len(nums)
        l=0
        r=lens-1
        mid=int((r+l)/2)
        #print("r=",r)
        #print("mid=",mid)

        if lens==0:
            return -1
        '''
        if lens==1:
            if nums[0]==target:
                return 0
            else:
                return -1
        
        if lens==2:
            if nums[0]==target:
                return 0
            else:
                if nums[1]==target:
                    return 1
                else:
                    return -1
        '''
        while(1):
            #print(nums[mid])
            if mid==lens-1:
                k=mid
                break
            if nums[mid]<nums[mid-1] and nums[mid]<nums[mid+1]:
                k=mid
                break
            else:
                if nums[mid]>nums[r]:
                    l=mid+1
                    mid=int((mid+1+r)/2)
                else:
                    r=mid-1
                    mid=int((mid-1+l)/2)
        #print("k=",k)
        #print("nums[k]=",nums[k])
        if target>=nums[k] and target<=nums[len(nums)-1]:
            l=k
            r=len(nums)-1
        else:
            if target>=nums[0] and target<=nums[k-1]:
                l=0
                r=k-1
            else:
                return -1

        #print("l=",l)  
        #print("r=",r)      
        
        mid=int((r+l)/2)
        while(l<=r):
            #print(nums[mid])
            if nums[mid]==target:
                return mid
            else:
                if nums[mid]<target:
                    l=mid+1
                    mid=int((mid+1+r)/2)
                else:
                    r=mid-1
                    mid=int((mid-1+l)/2) 
            #print("nums[mid]=",nums[mid])
        return -1       
        
            

43. 字符串相乘

给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。

class Solution:
    #def multiply(self, num1: str, num2: str) -> str:
    def multiply(self, num1: str, num2: str):
        print("num1=",num1)
        print("num2=",num2)
        l1=len(num1)
        l2=len(num2)
        re=[]
        nums=['']*l2
        numstr=['']*l2
        ad=0
        restr=''
        sum=0
        print("l1=",l1)
        print("l2=",l2)

        for i in range(l2):
            #print("l2-i-1=",l2-i-1)
            print("nums[l2-i-1]",num2[l2-i-1])
            for j in range(l1):
                #print("nums[l1-j-1]",num1[l1-j-1])
                temp=int(num2[l2-i-1])*int(num1[l1-j-1])
                #print("temp=",temp)
                if (temp+ad)<10:
                    re.append(str(temp+ad))
                    #print("re=",re)
                    ad=0
                else:
                    re.append(str((temp+ad)%10))
                    ad=int((temp+ad)/10)
                    #print("ad=",ad)
            print("re=",re)

            nums[i]=re
            if ad>0:
                re.append(str(ad))
            re=[]
            ad=0


        print("nums=",nums)
        for i in range(l2):
            print("nums[i]=",nums[i])
            lt=len(nums[i])
            for j in range(lt):
                #print(nums[i][lt-j-1])
                #print(i)
                #print(j)
                re.append(nums[i][lt-j-1])
                #print("re=",re)
                #print("numstr[i][j]=",numstr[i][j])
            print("re=",re)
            numstr[i]=re
            re=[]

        print("numstr=",numstr)

        for i in range(len(numstr)):
            for j in range(len(numstr[i])):
                print(numstr[i][j])
                restr+=numstr[i][j]
            print("restr=",restr)
            sum=sum+int(restr)*10**i
            restr=''
        print("sum=",sum)
        print("sum=",str(sum))
        sumstr=str(sum)

        return sumstr




54. 螺旋矩阵

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> ans;
        if(matrix.size() == 0)
            return ans;
        int m = matrix.size();
        int n = matrix[0].size();
        int l_left = 0, l_right = m - 1;
        int r_left = 0, r_right = n - 1;
        while(l_left <= l_right && r_left <= r_right)
        {
            for(int i = r_left; i <= r_right; i ++)
                ans.push_back(matrix[l_left][i]);
            if(l_left + 1 <= l_right - 1)//两行中间还有一行或多行,否则竖着的没有可输出的
                for(int i = l_left + 1; i <= l_right - 1; i ++)
                    ans.push_back(matrix[i][r_right]);
            if(l_left != l_right)//不是只有一行
                for(int i = r_right; i >= r_left; i --)
                    ans.push_back(matrix[l_right][i]);
            if(l_left + 1 <= l_right - 1 && r_left != r_right)
//两行中间还有一行或多行,并且不是只有一列
                for(int i = l_right - 1; i >= l_left + 1; i --)
                    ans.push_back(matrix[i][r_left]);
            l_left ++;
            l_right --;
            r_left ++;
            r_right --;
        }
 
        return ans;
    }
};

122. 买卖股票的最佳时机 II

给定一个数组 prices ,其中 prices[i] 表示股票第 i 天的价格。

在每一天,你可能会决定购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以购买它,然后在 同一天 出售。
返回 你能获得的 最大 利润 。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int l=prices.size();
        int k=0;
        for(int i=1;i<l;i++)
        {
            if(prices[i]>prices[i-1])
            {
                k=k+(prices[i]-prices[i-1]);
                cout<<"k="<<k<<endl;
            }
        }
        return k;
        
    }
};

5. 最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。

 class Solution {
    public:
    int f(string &s,int i,int len)
    {
        int l1=1;
        int l2=1;
        int l=i-1;
        int r=i+1;
        while(l>=0&&r<len)
        {
            if(s[l]==s[r])
                l1+=2;
            else
                break;
            l--;
            r++;
        }
        for (l = i, r = i+1; l >= 0 && r < s.size() && s[l] == s[r]; l--, r++);
        l2 = r - l - 1;
        return max(l1, l2);
    }
    string longestPalindrome(string s) {
        //中心扩展法
        int len=s.size();
        if(len<=1)
            return s;
        int max_len=0,start=0;
        for(int i=0;i<len;++i)
        {
            //cout<<"s="<<s<<endl;
            //cout<<"i="<<i<<endl;
            //cout<<"len="<<len<<endl;
            int temp=f(s,i,len);
            //cout<<"temp="<<temp<<endl;
            if(temp>max_len)
            {
                max_len=temp;
                start=i-(temp-1)/2;
            }
        }
        return s.substr(start,max_len);     
    }
    };

59. 螺旋矩阵 II

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> result;
        vector<int> re;
        int temp[n][n];
        int flag[n][n];
        int addflag=1;//0表示i递增,1表示是j递增。
        int i=0;
        int j=0;
        int ki=1,kj=1;

        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                temp[i][j]=0;
                flag[i][j]=0;

            }
        }

        i=0;j=0;
        //cout<<"i="<<i<<endl;
        //cout<<"j="<<j<<endl;        
        for(int t=1;t<=n*n;t++)
        {
            //cout<<i+1<<endl;  
            temp[i][j]=t;
            flag[i][j]=1;
            //cout<<"temp="<<temp[i][j]<<endl;   
            //cout<<"addflag="<<addflag<<endl;   

            if(addflag==0 && i+ki<n && i+ki>=0 && flag[i+ki][j]==0)//i递增
            {
                cout<<"i递增"<<endl;
                i=i+ki;
            }
            else if(addflag==0 && (i+ki>=n || i+ki<0 || flag[i+ki][j]==1 ) )//i暂停
            {
                cout<<"i暂停"<<endl;
                addflag=1;
                ki=-ki;
            }

            if(addflag==1 && j+kj<n && j+kj>=0 && flag[i][j+kj]==0)  //j递增
            {
                cout<<"j递增"<<endl;
                j=j+kj;
            }
            else if(addflag==1 && (j+kj>=n || j+kj<0|| flag[i][j+kj]==1  )   )  //j暂停
            {
                cout<<"j暂停"<<endl;
                addflag=0;
                kj=-kj;

                i=i+ki;
            }            

            //cout<<"ki="<<ki<<"kj="<<kj<<endl;
            //cout<<"i="<<i<<endl;
            //cout<<"j="<<j<<endl;
            

        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                //cout<<"temp="<<temp[i][j]<<endl;
                re.push_back(temp[i][j]);
            }
            result.push_back(re);
            re.clear();
        }

        return result;



        
    }
};

61. 旋转链表

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {

        ListNode* temp=head;
        int n=0;

        if(head==NULL || head->next==NULL)
        {
            return head;
        }
        while(temp!=NULL)
        {
            n=n+1;
            temp=temp->next;
        }
        cout<<"n="<<n<<endl;
        temp=head;

        k=k%n;
        cout<<"k="<<k<<endl;

        for(int i=0;i<k;i++)
        {
            temp=RightOne(temp);
            cout<<"temp->val="<<temp->val<<endl;
        }
        return temp;


    }

    ListNode* RightOne(ListNode* head)
    {
        ListNode* p=head;
        ListNode* q;
        ListNode* t=head;

        while(t->next->next!=NULL)
        {
            t=t->next;
        }
        q=t->next;
        cout<<"t->val="<<t->val<<endl;
        cout<<"q->val="<<q->val<<endl;

        q->next=p;
        t->next=NULL; 
        return q;       
    }
};

62. 不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

class Solution {
public:
    int uniquePaths(int m, int n) {
        int s[m][n];

        for(int i=1;i<n;i++)
        {
            s[0][i]=1;
        }

        for(int i=1;i<m;i++)
        {
            s[i][0]=1;
        }  

        for(int i=1;i<m;i++)      
        {
            for(int j=1;j<n;j++)
            {
                s[i][j]=s[i-1][j]+s[i][j-1];
            }
        }

        cout<<"s[m-1][n-1]="<<s[m-1][n-1]<<endl;
        return s[m-1][n-1];
        
    }
};

78. 子集

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {

        vector<vector<int>> result;
        vector<vector<int>> temp,temp1,temp2;
        vector<int> te;


        int l=nums.size();
        int rl=0;
        //cout<<"l="<<l<<endl;
        result.push_back(te);
        rl=result.size();
        //cout<<"rl="<<rl<<endl;
        

        /*for(int i=-1;i<l;i++)
        {
            if(i==-1)
            {
               result.push_back(te); 
            }
            else
            {
                te.push_back(nums[i]);
                result.push_back(te); 
                te.pop_back();
            }
        }*/



        for(int i=0;i<l;i++)
        {
            //cout<<"nums[i]="<<nums[i]<<endl;
            rl=result.size();
            //cout<<"rl="<<rl<<endl;
            for(int j=0;j<rl;j++)
            {
                //cout<<"result[j][0]="<<result[j][0]<<endl;
                //te=result[j];
                //te.swap(result[j]);
                vector<int> newtemp = result[j];
                //cout<<"te[0]="<<te[0]<<endl;
                //newtemp.push_back(nums[i]);
                newtemp.insert(newtemp.end(),nums[i]);
                //cout<<"te[0]="<<te[0]<<"te[1]="<<te[1]<<endl;
                result.push_back(newtemp);

            }
        }



        return result;
        

        

        
    }
};

89. 格雷编码

n 位格雷码序列 是一个由 2n 个整数组成的序列,其中:

  • 每个整数都在范围 [0, 2n - 1] 内(含 0 和 2n - 1
  • 第一个整数是 0
  • 一个整数在序列中出现 不超过一次
  • 每对 相邻 整数的二进制表示 恰好一位不同 ,且
  • 第一个 和 最后一个 整数的二进制表示 恰好一位不同

给你一个整数 n ,返回任一有效的 n 位格雷码序列 。

class Solution {
public:
    vector<int> grayCode(int n) {
        int l=pow(2,n);
        int te;
        vector<int> result;
        cout<<"l="<<l<<endl;
        for(int i=0;i<l;i++)
        {
            te=i^(i/2);
            //cout<<"te="<<te<<endl;
            result.push_back(te);
        }

        return result;
        
    }
};

142. 环形链表 II

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *p=head;
        ListNode *r;
        r=NULL;
        vector<ListNode*>::iterator it;
        vector<ListNode*> te;

        if(head==NULL)
        {
            return NULL;
        }
        while(p->next!=NULL)
        {
            it=find(te.begin(),te.end(),p);
            if(it!=te.end())
            {
                r=p;
                break;
            }
            else
            {
                te.push_back(p);
                p=p->next;
            }
        }

        return r;
        
    }
};

146. LRU 缓存

请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

class LRUCache {
public:
     int n;
    list<pair<int, int>> lis;
    map<int, list<pair<int, int>>::iterator> mp;
    LRUCache(int capacity) 
    {
         n = capacity; //初始化缓存大小
    }
    int get(int key) 
    {
        int ret = -1;     
        if(mp.find(key) != mp.end())
        { // 缓存中已经存在key    
            auto iter = mp[key];     
            ret = iter->second;   
            lis.erase(iter);  //在链表中删除这个key和value            
            lis.push_front(make_pair(key, ret));  //再把这个key和value放在链表的表头         
            mp[key] = lis.begin();  //同时,要更新map中key所指向链表的位置      
        }  
        return ret;  //返回value值
    }
    
    void put(int key, int value) 
    {
        auto iter = mp.find(key);  //看看map中是否有这个key        
        if(iter != mp.end())
        {  //如果有,则更新这个key在链表中的顺序,需先删除,然后再push_front在表头          
            lis.erase(iter->second);  
        }      
        else if(lis.size() < n)
        { 
            //如果链表中的元素个数小于可缓存数      
        }      
        else
        { 
            //list中没有key,且已超过n个   
            int key = lis.back().first;   
            lis.pop_back();   //擦除最少使用的key value对            
            mp.erase(key);    //同时擦除map中对应的元素  
        }      
        lis.push_front(make_pair(key, value));  
        mp[key] = lis.begin();
    }
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */

215. 数组中的第K个最大元素

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

class Solution {

public:
    int findKthLargest(vector<int>& nums, int k) {
        
        priority_queue<int> q;

        /*for_each(nums.begin(), nums.end(), [&](int i) 
        { q.push(i); });*/
        for(int i=0;i<nums.size();i++)
        {
            q.push(nums[i]);
        }

        for(int i = 0; i < k - 1; i++)  q.pop();

        return q.top();
    }
};

148. 排序链表​​​​​​​

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        //priority_queue<int> t;
        priority_queue<int, vector<int>, greater<int> > t;
        ListNode *p;
        p=head;
        while(p!=NULL)
        {
            //cout<<"p->val="<<p->val<<endl;
            t.push(p->val);
            p=p->next;
        }

        p=head;
        while(p!=NULL)
        {
            p->val=t.top();
            //cout<<"p->val="<<p->val<<endl;
            t.pop();
            p=p->next;
        }

        return head;


    }
};

230. 二叉搜索树中第K小的元素

给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int kthSmallest(TreeNode* root, int k) {
        priority_queue<int, vector<int>, greater<int> > t;
        stack<TreeNode*> re;
        TreeNode* p=root;
        //TreeNode* te;
        int n=0;
        int te;

        while(p!=NULL || !re.empty() )
        {
            //n=n+1;
            while(p!=NULL)
            {
                re.push(p);
                p=p->left;
            }
            p=re.top();
            cout<<"p->val="<<p->val<<endl;
            n=n+1;
            re.pop();
            //te=re.top();
            //cout<<"t->val="<<te->val<<endl;
            if(n==k)
            {
                te=p->val;
            }
            p=p->right;

        }

        return te;
        
        
    }
};

236. 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

/**
 * 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:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> re;
        stack<TreeNode*> ps;
        stack<TreeNode*> qs;
        stack<TreeNode*> exps;
        stack<TreeNode*> exqs;
        stack<TreeNode*> temp;
        TreeNode* t;
        TreeNode* pt;
        TreeNode* qt;
        TreeNode* te1;
        TreeNode* te2;
        t=root;
        int pflag=0;
        int qflag=0;
        while(t!=NULL || (pflag<1 || qflag<1)  )
        {
            if(t==NULL)
            {
                te1=re.top();
                re.pop();
                //cout<<"te1->val="<<te1->val<<endl;
                te2=re.top();
                if(te2->left==te1)
                {
                    te2->left=NULL;
                }
                else if(te2->right==te1)
                {
                    te2->right=NULL;
                }

                
                t=root;
            }
            //cout<<"t->val="<<t->val<<endl;
            re.push(t);
            
            if(t==p)
            {
                pflag=1;

                temp=re;
                
                te1=temp.top();
                while(te1!=root)
                {
                    ps.push(te1);
                    //cout<<"ps->val="<<te1->val<<endl;
                    temp.pop();
                    te1=temp.top();

                }
                te1=root;
                //cout<<"ps->val="<<te1->val<<endl;
                ps.push(te1);


                

            }
            if(t==q)
            {
                qflag=1;

                temp=re;
                
                te1=temp.top();
                while(te1!=root)
                {
                    qs.push(te1);
                    //cout<<"qs->val="<<te1->val<<endl;
                    temp.pop();
                    te1=temp.top();

                }
                te1=root;
                //cout<<"qs->val="<<te1->val<<endl;
                qs.push(te1);                
            }


            if(t->left!=NULL)
            {
                t=t->left;
            }
            else
            {
                t=t->right;
            }
        }

        /*ps  qs颠倒*/
        while(!ps.empty())
        {
            t=ps.top();
            //cout<<"tt1->val="<<t->val<<endl;
            exps.push(t);
            ps.pop();
        }

        while(!qs.empty())
        {
            t=qs.top();
            //cout<<"tt2->val="<<t->val<<endl;
            exqs.push(t);
            qs.pop();
        }        

        

        pt=exps.top();
        while(pt!=NULL)
        {
            //qt=exqs.top();
            temp=exqs;
            qt=temp.top();
            cout<<"pt->val="<<pt->val<<endl;
            while(!temp.empty())
            {
                cout<<"qt->val="<<qt->val<<endl;
                if(qt==pt)
                {
                    //cout<<"qttest->val="<<qt->val<<endl;
                    return qt;
                }
                //cout<<"qtend1->val="<<qt->val<<endl;
                temp.pop();
                qt=temp.top();
                //cout<<"qtend2->val="<<qt->val<<endl;
            }

            exps.pop();
            pt=exps.top();
            //cout<<"ptend->val="<<pt->val<<endl;


        }

        return qt;
        
        
    }
};

238. 除自身以外数组的乘积

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。

题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在  32 位 整数范围内。

不要使用除法,且在 O(n) 时间复杂度内完成此题。

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {

        int l=nums.size();
        vector<int> result(l);

        //cout<<"nums="<<nums[l-1]<<endl;
        result[l-1]=nums[l-1];
        
        //cout<<"result="<<result[l-1]<<endl;
        for (int i=l-2;i>=0;i--)
        {
            result[i]=result[i+1]*nums[i];
            //cout<<"result="<<result[i]<<endl;
        }

        for (int i=1;i<l;i++)
        {
            nums[i]=nums[i-1]*nums[i];
            //cout<<"nums="<<nums[i]<<endl;
        } 

        for (int i=0;i<l;i++)
        {
            if(i==0)
            {
                result[i]=result[i+1];
            }
            else if(i==l-1)
            {
                result[i]=nums[i-1];
            }
            else
            {
                result[i]=nums[i-1]*result[i+1];
            }
        }



        return result;

    }
};

198. 打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

class Solution {
public:
    int rob(vector<int>& nums) {
        int l=nums.size();
        vector<int> re;
        //re[0]=nums[0];
        if(l==0)
        {
            return 0;
        }

        if(l==1)
        {
            return nums[0];
        }

        if(l==2)
        {
            return max(nums[0],nums[1]);
        }

        re.push_back(nums[0]);
        //re[1]=max(nums[0],nums[1]);
        re.push_back(max(nums[1],nums[0]));
        cout<<"re[0]="<<re[0]<<endl;
        cout<<"re[1]="<<re[1]<<endl;
        int temp;

        for(int i=2;i<l;i++)
        {
            temp=max(re[i-2]+nums[i],re[i-1]);
            cout<<"temp="<<temp<<endl;
            re.push_back(temp);
        }

        return temp;
    }
};

538. 把二叉搜索树转换为累加树

给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

提醒一下,二叉搜索树满足下列约束条件:

  • 节点的左子树仅包含键 小于 节点键的节点。
  • 节点的右子树仅包含键 大于 节点键的节点。
  • 左右子树也必须是二叉搜索树。

注意:本题和 1038: 力扣 相同

/**
 * 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 {

int val=0;    
public:
    TreeNode* convertBST(TreeNode* root) {

        if(root==NULL)
        {
            return root;
        }

        convertBST(root->right);

        root->val=root->val+val;

        val=root->val;

        cout<<"val="<<val<<endl;

        convertBST(root->left);
        

        return root;

    }
};

19. 删除链表的倒数第 N 个结点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        stack<ListNode*> temp;
        ListNode* p;
        ListNode* q=NULL;
        p=head;
        int k=n;

        if(p==NULL || p->next==NULL)
        {
            return q;
        }

        while(p)
        {
            temp.push(p);
            p=p->next;
        }

        while(k>=0 && !temp.empty())
        {
           p=temp.top();
           temp.pop();
           k=k-1;
        }

        cout<<"k="<<k<<endl;

        cout<<"p="<<p->val<<endl;
        if(p==head && k!=-1)
        {
            head=head->next;
        }
        else
        {
            if(p->next->next!=NULL)
            {
                p->next=p->next->next;
            }
            else
            {
                p->next=NULL;
            }
            
        }

        
        return head;


        
    }
};

22. 括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        
        vector<string> res;
        int l=0;
        int r=0;
        deal("",res,n,l,r);
        return res;
        
    }

    void deal(string str,vector<string> &res, int n, int l,int r)
    {
        if(r==n)
        {
            //cout<<"push_str="<<str<<endl;
            res.push_back(str);
        }

        if(l<n)
        {
            //cout<<"str="<<str<<endl;
            deal(str+'(',res,n,l+1,r);
        }

        if(r<l)
        {
            //cout<<"str="<<str<<endl;
            deal(str+')',res,n,l,r+1);
        }


    }
};

34. 在排序数组中查找元素的第一个和最后一个位置

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

进阶:

  • 你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        
        vector<int> re;
        int t;

        int flag=0;

        for(int i=0;i<nums.size();i++)
        {
            if(nums[i]==target)
            {

                if(flag<=1)
                {
                    re.push_back(i);
                    flag=flag+1;                   
                }

                if(flag>=2)
                {
                    re.pop_back();
                    re.push_back(i);
                    flag=flag+1;
                }
            }

        }

        if(re.size()==0)
        {
            re.push_back(-1);
            re.push_back(-1);
        }

        if(re.size()==1)
        {
            t=re.back();
            re.push_back(t);
        }        

        return re;

    }
};

46. 全排列

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

class Solution {
public:

vector<vector<int>> ans;
    void dfs(int begin,int n,vector<int> &use,vector<int> &num,vector<int> nums){
        if(begin == n){
            ans.push_back(num);
        }
        if(begin<n){
            for(int i=0; i<n; i++){
                if(!use[i]){		//选取没有选过的数
                    use[i]=1;
                    num.push_back(nums[i]);
                    //cout<<num[0]<<num[1]<<num[2]<<endl;
                    dfs(begin+1,n,use,num,nums);
                    //cout<<"test="<<num[0]<<num[1]<<num[2]<<endl;
                    cout<<"test=";
                    for(int k=0;k<num.size();k++)
                    {
                        cout<<num[k];
                        
                    }
                    cout<<endl;
                    //cout<<"num.sizet="<<num.size()<<endl;
                    use[i]=0;
                    num.pop_back();
                    //cout<<num[0]<<num[1]<<num[2]<<endl;
                    //cout<<"num.size="<<num.size()<<endl;
                    for(int k=0;k<num.size();k++)
                    {
                        cout<<num[k];
                        
                    }
                    cout<<endl;
                }
            }
        }
    }
    vector<vector<int>> permute(vector<int>& nums) {
        int n=nums.size();
        vector<int> use(n,0);
        vector<int> num;
        dfs(0,n,use,num,nums);
        return ans;
    }

};

48. 旋转图像

给定一个 × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {

        int l=matrix.size();
        cout<<"l="<<l*l/2<<endl;
        vector<int> mid;
        int temp;
        int k=0;

        for(int i=0;i<l;i++)
        {
            for(int j=i;j<l;j++)
            {
                //cout<<"matrix="<<matrix[i][j]<<endl;
                //cout<<"matrixsu="<<matrix[j][l-i-1]<<endl;
                temp=matrix[i][j];
                matrix[i][j]=matrix[j][i];
                matrix[j][i]=temp;
                //cout<<"matrix1="<<matrix[i][j]<<endl;
                k=k+1;
                /*if(k=l*l/2)
                {
                    return;
                }*/
            }
        }

        for(int i=0;i<l;i++)
        {
            for(int j=0;j<l/2;j++)
            {
                temp=matrix[i][j];
                matrix[i][j]=matrix[i][l-j-1];
                matrix[i][l-j-1]=temp;
            }
        }        

        //return matrix;
        
    }
};

55. 跳跃游戏

给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

class Solution {
public:
	bool canJump(vector<int>& nums) {
		int maxStep = 0;
		for (int i = 0; i < nums.size() - 1 && maxStep>=i; ++i) {
			maxStep=max(maxStep,i+nums[i]);
            cout<<"max="<<maxStep<<endl;
		}
        if(maxStep>=nums.size()-1)
        {
            return 1;
        }
        else
        {
            return 0;
        }
	}
};

56. 合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {

        vector<vector<int>> re;
        vector<int> te;
        int l=intervals.size();
        int minTe,maxTe;

        sort(intervals.begin(),intervals.end());


        if(l==0 || l==1)
        {
            return intervals;
        }

        for(int i=0;i<l-1;i++)
        {
            //te.push_back(intervals[i][0]);
            //te.push_back(intervals[i][1]);
            te=intervals[i];

            //if(intervals[i+1][1]<=intervals[i][0] ||intervals[i+1][0]<=intervals[i][1])
            //if(intervals[i+1][0]<=intervals[i][1] && )
            if(max(intervals[i][0],intervals[i+1][0])<=  min(intervals[i][1],intervals[i+1][1]) )
            {
                minTe=min(intervals[i][0],intervals[i+1][0]);
                maxTe=max(intervals[i][1],intervals[i+1][1]);

                cout<<"minTe="<<minTe<<endl;
                cout<<"maxTe="<<maxTe<<endl;

                te.clear();
                te.push_back(minTe);
                te.push_back(maxTe);

                intervals[i+1][0]=minTe;
                intervals[i+1][1]=maxTe;

            }
            else
            {
                re.push_back(te);
                te.clear();
            }






        }

        if(!te.empty())
        {
            re.push_back(te);
        }

        //处理没有被合并的最后一个区间
        if(max(intervals[l-2][0],intervals[l-1][0])>  min(intervals[l-2][1],intervals[l-1][1]))
        {
            re.push_back(intervals[l-1]);
        }       

        return re;




    }

    /*bool comp(const student &a, const student &b){
        return a.score < b.score;
    }*/
        

};

64. 最小路径和

给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {

        int m=grid.size();
        int n=grid[0].size();
        vector<vector<int>> re;
        vector<int> te;
        int temp;

        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                //cout<<"i="<<i<<",j="<<j<<endl;
                if(i==0 && j==0)
                {
                    //cout<<"grid[i][j]="<<grid[i][j]<<endl;
                    //cout<<"re[i][j]="<<re[i][j]<<endl;
                    temp=grid[i][j];
                    //cout<<"test"<<endl;
                    //re[i][j]=grid[i][j];
                    te.push_back(temp);
                    //cout<<"test1"<<endl;
                    //cout<<"temp="<<temp<<endl;
                   
                }
                else if(i==0)
                {
                    //re[i][j]=re[i][j-1]+grid[i][j];
                    temp=te.back()+grid[i][j];
                    te.push_back(temp);                   
                    //cout<<"temp="<<temp<<endl;
                }
                else if(j==0)
                {
                    //re[i][j]=re[i-1][j]+grid[i][j];
                    //cout<<"re[i-1][j]="<<re[i-1][j]<<endl;
                    //cout<<"grid[i][j]="<<grid[i][j]<<endl;
                    temp=re[i-1][j]+grid[i][j];
                    te.push_back(temp);
                    //cout<<"temp="<<temp<<endl;
                }
                else
                {
                    //re[i][j]=min(re[i-1][j],re[i][j-1])+grid[i][j];
                    temp=min(re[i-1][j],te.back())+grid[i][j];
                    te.push_back(temp);
                    //cout<<"temp="<<temp<<endl;                    
                }

                //cout<<"re[i][j]="<<re[i][j]<<endl;

            }
            re.push_back(te);
            te.clear();
        }

        return re[m-1][n-1];
        
    }
};

75. 颜色分类

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

必须在不使用库的sort函数的情况下解决这个问题。

class Solution {
public:
    void sortColors(vector<int>& nums) {

        int r=0,w=0,b=0;

        for(int i=0;i<nums.size();i++)
        {
            if(nums[i]==0)
            {
                r=r+1;
            }

            if(nums[i]==1)
            {
                w=w+1;
            }

            if(nums[i]==2)
            {
                b=b+1;
            }
        }

        //cout<<"r="<<r<<endl;
        //cout<<"w="<<w<<endl;
        //cout<<"b="<<b<<endl;

        for(int i=0;i<nums.size();i++)
        {
            if(i<r)
            {
                nums[i]=0;
            }
            else if(i>=r && i<r+w)
            {
                nums[i]=1;
            }
            else if(i>=r+w && i<r+w+b)
            {
                nums[i]=2;
            }
        }

    }
};

31. 下一个排列

整数数组的一个 排列  就是将其所有成员以序列或线性顺序排列。

  • 例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3][1,3,2][3,1,2][2,3,1] 。

整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。

  • 例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。
  • 类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。
  • 而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。

给你一个整数数组 nums ,找出 nums 的下一个排列。

必须 原地 修改,只允许使用额外常数空间。

class Solution {
public:
    void nextPermutation(vector<int>& nums) {

        int l=nums.size();
        int temp;
        int i;
        int k;
        int min_flag;
        int min=0;
        cout<<"l="<<l<<endl;
        for(i=l-1;i>0;i--)
        {
            if(nums[i]>nums[i-1])
            {
                //找出当前位比前一位大的位置,比如231的3.
                cout<<"nums[i-1]"<<nums[i-1]<<endl;
                min=nums[i];
                min_flag=i;
                cout<<"min="<<min<<endl;
                
                //找出可以替换i-1位置的值,取比i-1位置值大的最小值
                for(k=i;k<l;k++)
                {
                    cout<<"nums[k]="<<nums[k]<<endl;
                    if(nums[k]<min && nums[k]>nums[i-1])
                    {
                        min=nums[k];
                        min_flag=k;
                        cout<<"min="<<min<<endl;
                    }
                }
               
                //交换i-1位置值和可用最小值
                temp=nums[i-1];
                nums[i-1]=min;
                nums[min_flag]=temp;
                break;
            }
        }

        //i-1位置之后的部分排序
        if(i>0)
        {
            sort(nums.begin()+i, nums.end());
        }


        cout<<"i="<<i<<endl;
        cout<<"l/2="<<l/2<<endl;
        if(i==0)
        {
            for(int j=0;j<l/2;j++)
            {
                temp=nums[j];
                nums[j]=nums[l-j-1];
                nums[l-j-1]=temp;
                cout<<"temp="<<temp<<endl;
            }
        }
        
        
    }
};

96. 不同的二叉搜索树

给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。

class Solution {
public:
    int sum=0;
    int numTrees(int n) {

        int re;
        int sum;

        //为空也返回1,用于将整个列表都归于树的一侧使用
        if(n==0)
        {
            re=1;
            return re;
        }

        //一个节点,只能返回一个搜索二叉树
        if(n==1)
        {
            re=1;
            return re;
        }
        else if(n==2)//多直接返回几个场景,提高效率
        {
            re=2;
            return re;
        }
        else if(n==3)
        {
            re=5;
            return re;
        }
        else if(n==4)
        {
            re=14;
            return re;
        }
        else if(n==5)
        {
            re=42;
            return re;
        }
        else
        {
            sum=0;

            //依次将列表中的每个结点作为根结点
            for(int k=1;k<=n;k++)
            {
                //左树*右树,累计每个结点作为根结点的返回数
                sum=sum+numTrees(k-1)*numTrees(n-k);
            }
        }

        re=sum;



        return re;
        
    }
};

98. 验证二叉搜索树

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左子树只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。
/**
 * 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:


    bool isValidBST(TreeNode* root) {

        int l_flag=0;
        int r_flag=0;

        int l_comp=1;
        int r_comp=1;

        int l_max;
        int r_min;

        //cout<<"root->val="<<root->val<<endl;

        //树为空
        if(root==NULL)
        {
            return 1;
        }
        else 
        {
            //cout<<"root->val="<<root->val<<endl;
            //左树
            l_flag=isValidBST(root->left);
            //cout<<"l_flag="<<l_flag<<endl;

            //右树
            r_flag=isValidBST(root->right);
            //cout<<"r_flag="<<r_flag<<endl;

            //判断左子树最大值是否小于树根
            if(root->left!=NULL)
            {
                l_comp=root->val>maxf(root->left);
                cout<<"root->val="<<root->val<<endl;
                cout<<"root->left->val="<<root->left->val<<endl;
                cout<<"maxf="<<maxf(root->left)<<endl;
                cout<<"l_comp="<<l_comp<<endl;
            }

            //判断右子树最小值是否大于树根
            if(root->right!=NULL)
            {
                r_comp=root->val<minf(root->right);
                cout<<"r_comp="<<r_comp<<endl;
            }

            return (l_flag && r_flag && l_comp && r_comp);
        }

        return 0;
        
    }

    //找树的最小值
    int minf(TreeNode* root)
    {
        int min;
        int l_min,r_min;
        if(root==NULL)
        {
            return 99999;
        }

        min=root->val;

        if(root->left!=NULL)
        {
            l_min=minf(root->left);
            if(l_min<min)
            {
                min=l_min;
            }
        }

        if(root->right!=NULL)
        {
            r_min=minf(root->right);
            if(r_min<min)
            {
                min=r_min;
            }
        } 

        return min;      


    }

    //找树的最大值
    int maxf(TreeNode* root)
    {
        int max;
        int l_max,r_max;
        if(root==NULL)
        {
            return -1;
        }

        max=root->val;

        if(root->left!=NULL)
        {
            l_max=maxf(root->left);
            if(l_max>max)
            {
                max=l_max;
            }
        }

        if(root->right!=NULL)
        {
            r_max=maxf(root->right);
            if(r_max>max)
            {
                max=r_max;
            }
        } 

        return max;      


    }



};

102. 二叉树的层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

/**
 * 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<vector<int>> levelOrder(TreeNode* root) {

        vector<vector<int>> re;

        vector<int> level_elment;//记每一层的无素

        TreeNode* front;
        queue<TreeNode*> temp;
        queue<int>  level;//记录在第几层

        int le;

        if(root==NULL)
        {
            return re;
        }
        
        //cout<<"root->val="<<root->val<<endl;

        //处理根结点
        temp.push(root);

        level.push(1);

        level_elment.push_back(temp.front()->val);
        re.push_back(level_elment);
        level_elment.clear();

        while(!temp.empty())
        {
            //记录当前在第几层
            le=level.front()+1;
            
            //取队列头结点
            front=temp.front();

            //队列头结点的左右子树结点入队列,层数入队列,元素入队列
            if(front->left!=NULL)
            {
                temp.push(front->left);
                level.push(level.front()+1);

                level_elment.push_back(front->left->val);
            }

            if(front->right!=NULL)
            {
                temp.push(front->right);
                level.push(level.front()+1);

                level_elment.push_back(front->right->val);
            } 

            //队列头出队列
            temp.pop();
            level.pop(); 

            //下一个元素在第几层,是否与当前层一致,如果在同一层则不清空level_elment
                     

            if(!level_elment.empty() && le<level.front()+1)
            {
                re.push_back(level_elment);  
                level_elment.clear();
            }
            
            
            cout<<"root->val="<<front->val<<endl;



        }



        return re;
        
    }

};

105. 从前序与中序遍历序列构造二叉树

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

/**
 * 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:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {

        TreeNode* root= new TreeNode();//返回

        TreeNode* left= new TreeNode();
        TreeNode* right= new TreeNode();

        vector<int> l_invec;
        vector<int> l_prevec;
        vector<int> r_invec;
        vector<int> r_prevec;

        int find_flag=0;//记录是否已找到
        int find_sta;//记录找到的位置

        int l=preorder.size();

        
        //cout<<preorder[0]<<endl;

        if(l==0)
        {
            return NULL;
        }

        root->val=preorder[0];

        if(l==1)
        {
            return root;
        }

        //找前序第一个结点在中序中的位置,将位置左边、右边分别存入向量,并且记下位置
        for(int i=0;i<l;i++)
        {
            if(preorder[0]==inorder[i])
            {
                find_flag=1;//标识已找到
                find_sta=i;//记下位置
                continue;
            }
            if(find_flag==0)//找到之前,
            {
                l_invec.push_back(inorder[i]);
            }
            else if(find_flag==1)//找到后
            {
                r_invec.push_back(inorder[i]);
            }
        }

        //根据记下的位置find_sta,将前序分左右分别存入向量
        for(int i=1;i<l;i++)
        {
            if(i<=find_sta)
            {
                l_prevec.push_back(preorder[i]);
            }
            else
            {
                r_prevec.push_back(preorder[i]);
            }
        }

        //打印
        /*
        cout<<"l_pre=";
        for(int i = 0; i < l_prevec.size(); ++i) {
            
            std::cout  <<l_prevec[i] << " ";
        }

        cout<<endl;

        cout<<"r_pre=";
        for(int i = 0; i < r_prevec.size(); ++i) {
            
            std::cout  <<r_prevec[i] << " ";
        }
        cout<<endl;

        cout<<"l_in=";
        for(int i = 0; i < l_invec.size(); ++i) {
            
            std::cout  <<l_invec[i] << " ";
        }
        cout<<endl;


        cout<<"r_in=";
        for(int i = 0; i < r_invec.size(); ++i) {
            
            std::cout << r_invec[i] << " ";
        }
        cout<<endl; 
        */
            
        //cout<<"test2"<<endl;

        left=buildTree(l_prevec,l_invec);
        right=buildTree(r_prevec,r_invec);

        root->left=left;
        root->right=right;

        return root;
       
    }
};

114. 二叉树展开为链表

给你二叉树的根结点 root ,请你将它展开为一个单链表:

  • 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
  • 展开后的单链表应该与二叉树 先序遍历 顺序相同。
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> preList;

    void flatten(TreeNode* root) {

        TreeNode *re=new TreeNode();
        TreeNode *temp=new TreeNode();

        TreeNode *p=new TreeNode();

        //vector<int> preList;

        //树为空,或只有根结点,啥也不做
        if(root==NULL)
        {
            return;
        }
        else if(root->left==NULL && root->right==NULL)
        {
            return;
        }

        //先序遍历
        preorder(root);       
        /*for (const auto &c : preList) cout << c << " ";
        cout<<endl;*/


        p=root;       
        int l=preList.size();
        cout<<"l="<<l<<endl;

        //用先序遍历的结果重新塑造树
        for(int i=1;i<l;i++)
        {
            cout<<"preList.val="<<preList[i]<<endl;
            p->left=NULL; //左结点都置空           
            //p=p->right;

            //右结点存在,则直接改变值
            if(p->right!=NULL)
            {
                p->right->val=preList[i];
                cout<<"p->right->val="<<p->right->val<<endl;
                p=p->right;
            }
            else//右结点不存在,则生成一个结点,接上
            {
                TreeNode *temp=new TreeNode();//注意,容易出错
                temp->val=preList[i];
                p->right=temp;
                p=p->right;
            }
            
            
        }
    };

    
    
    
    
    
    int preorder(TreeNode* root)
    {
        if(root!=NULL)
        {
            //cout<<"root->val="<<root->val<<endl;
            preList.push_back(root->val);

            if(root->left!=NULL)
            {
                preorder(root->left);
            }

            if(root->right!=NULL)
            {
                preorder(root->right);
            } 
        }

        return 1;

    };
};

139. 单词拆分

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。

注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {

        int l=s.size();

        //标识从开始或上一个被拆分的点到当前位置是否可拆分
        //比string多一位,第0位初始值为1,从第1位开始保存到当前位置是否可拆分
        vector<int> flag(l+1,0);       
        flag[0]=1;
        int fl;

        for(int i=0;i<l;i++)
        {
            //cout<<"i="<<i<<endl;
            for(int j=0;j<=i;j++)
            {
                //cout<<"sub="<<s.substr(j,i-j+1)<<endl;

                //从j到i,是可以分割的
                fl=find(s.substr(j,i-j+1),wordDict);
                //cout<<"i="<<i<<" ";
                //cout<<"j="<<j<<" ";
                //cout<<"fl="<<fl<<" ";
                //cout<<"flag["<<j<<"]="<<flag[j]<<" "<<endl;

                //并上从0到j是否可分割
                if(fl==1 && flag[j]==1)
                {
                    flag[i+1]=1;                   
                    break;
                }
                //cout<<"fl="<<fl<<endl;
                
            }
            //cout<<"flag["<<i+1<<"]="<<flag[i+1]<<endl;
        }

        //cout<<"end="<<flag[l-1]<<endl;

        return flag.back();

    }

    //查找str是否在wordDict中
    int find(string str,vector<string>& wordDict)
    {
        int n=wordDict.size();

        for(auto word : wordDict)
        {
            //cout<<"word="<<word<<endl;
            if(str==word)
            {
                return 1;
            }
        }

        return 0;
    }
};

152. 乘积最大子数组

给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。

测试用例的答案是一个 32-位 整数。

子数组 是数组的连续子序列。

class Solution {
public:
    int maxProduct(vector<int>& nums) {

        int l=nums.size();

        vector<int> maxL(l,0);
        vector<int> minL(l,0);

        maxL[0]=nums[0];
        minL[0]=nums[0];

        int maxRe;

        for(int i=1;i<l;i++)
        {
            cout<<"max[i-1]="<<maxL[i-1]<<" ";
            cout<<"min[i-1]="<<minL[i-1]<<" ";
            cout<<"nums[i]="<<nums[i]<<" "<<endl;;
            maxL[i]=max(maxL[i-1]*nums[i],max(nums[i],minL[i-1]*nums[i]));
            minL[i]=min(maxL[i-1]*nums[i],min(nums[i],minL[i-1]*nums[i]));
            //maxL[i]=max(1,2);
            cout<<"maxL="<<maxL[i]<<endl;
            cout<<"minL="<<minL[i]<<endl;
        }

        maxRe=maxL[0];
        for(int i=1;i<l;i++)
        {
            if(maxL[i]>maxRe)
            {
                maxRe=maxL[i];
            }
        }

        return maxRe;


    }
};

200. 岛屿数量

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {

        int sum=0;
        int m=grid.size();
        cout<<"m="<<m<<endl;
        if(m==0)
        {
            return sum;
        }
        int n=grid[0].size();       

        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(grid[i][j]=='1')
                {
                    cout<<"test"<<endl;
                    sum=sum+1;
                    set(i,j,grid);
                }
            }
        }

        return sum;

    }

    //给当前位置周围为1的元素置为了2
    void set(int m,int n,vector<vector<char>>& grid)
    {
        //位置溢出或元素为1,则跳出
        if(m<0 || m>grid.size()-1 || n<0 ||n>grid[0].size()-1 || grid[m][n]!='1')
        {
            return;
        }
        else
        {
            grid[m][n]='2';
            set(m-1,n,grid);
            set(m+1,n,grid);
            set(m,n-1,grid);
            set(m,n+1,grid);
        }
    }
};

300. 最长递增子序列

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        if(n == 0)
            return 0;
        vector<int> dp(n, 1);
        int max_len = 1;
        
        for(int i = 1; i < n; i++)
        {
            //cout<<"nums[i]="<<nums[i]<<endl;
            for(int j = 0; j < i; j++)
            {
                if(nums[j] < nums[i])
                {
                    dp[i] = max(dp[i], dp[j]+1);
                }
                //cout<<"dp[i]="<<dp[i]<<endl;
            }
            max_len = max(max_len, dp[i]);
        }
        return max_len;
    }
};

347. 前 K 个高频元素

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

class Solution {
public:

    struct CmpByValue {  
        bool operator()(const pair<int,int>& lhs, const pair<int,int>& rhs) {  
            return lhs.second > rhs.second;  
        }  
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {

        vector<int> re;
        map<int, int> count;
        map<int,int>::iterator it;
        
        sort(nums.begin(),nums.end());

        count[nums[0]]=1;
        for(int i=1;i<nums.size();i++)
        {
            cout<<"nums[i]="<<nums[i]<<endl;
            if(nums[i]==nums[i-1])
            {
                count[nums[i]]=count[nums[i]]+1;
            }
            else
            {
               count[nums[i]]=1; 
            }
        }

        /*for(it = count.begin(); it != count.end(); it++)
        {
            cout<<it->first<<":"<<it->second<<endl;
        }*/

        // 将map中的内容转存到vector中
        vector<pair<int, int>> vec(count.begin(), count.end());

        sort(vec.begin(),vec.end(),CmpByValue());

        /*for(int j=0;j<vec.size();j++)
        {
            cout<<vec[j].first<<":"<<vec[j].second<<endl;
        }*/

        for(int j=0;j<k;j++)
        {
            cout<<vec[j].first<<":"<<vec[j].second<<endl;
            re.push_back(vec[j].first);
        }

       return re;

    }
};

给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指在第 i 天之后,才会有更高的温度。如果气温在这之后都不会升高,请在该位置用 0 来代替。

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& T) {

        int n=T.size();

        int te;

        vector<int> re(n,0);

        //逆序处理,最后一个元素re值为0

        re[n-1]=0;
        for(int i=n-2;i>=0;i--)
        {
            //如果后面一个元素大于当前元素,为1
            if(T[i+1]>T[i])
            {
                re[i]=1;
                continue;
            }
            else//如果后面一个元素不大于当前元素
            {
                //后面一个元素,找不到更高气温
                if(re[i+1]==0)
                {
                    re[i]=0;
                    continue;
                }
                else //后面一个元素不大于当前元素,但后面一个元素已找到更高气温
                {
                    //后面一个元素,更高气温的位置,记录下来
                    //cout<<"T[i]="<<T[i]<<endl;
                    te=i+1+re[i+1];
                    //cout<<"te="<<te<<endl;

                    while(1)
                    {
                        //后面一个元素,的更高气温的位置,的气温,是否大于当前气温
                        //cout<<"te="<<te<<endl;
                        if(T[te]>T[i])
                        {
                            //cout<<"test="<<endl;
                            re[i]=te-i;
                            break;
                        }
                        else
                        {
                            if(re[te]==0)
                            {
                               re[i]=0; 
                               break;
                            }
                            else
                            {
                                te=te+re[te];
                            }
                        }
                    }
                }
            }
        }

        return re;




    }
};

647. 回文子串

给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。

回文字符串 是正着读和倒过来读一样的字符串。

子字符串 是字符串中的由连续字符组成的一个序列。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

class Solution {
public:
    int countSubstrings(string s) {

        int cnt=0;

        int l=s.size();

        int re[l][l];

        for(int i=0;i<l;i++)
        {
            for(int j=0;j<l;j++)
            {
                re[i][j]=0;
            }
        }

        //re[0][0]=1;
        //int[][] re=int[s.size()][s.size()];

        for(int i=s.size()-1;i>=0;i--)
        {
            for(int j=s.size()-1;j>=i;j--)
            {
                //单字符是回文
                if(i==j)
                {
                    //cout<<"i="<<i<<endl;
                    //cout<<"j="<<j<<endl;
                    re[i][j]=1;
                }
                else //多个字符
                {
                    //跨度不超过3
                    if(j-i<=2)
                    {
                        //比较首尾是不是相同即可
                        if(s[i]==s[j])
                        {
                          re[i][j]=1;  
                        }
                    }
                    else//跨度超过3
                    {
                        //首尾相同,且中间部分是回文
                        if(s[i]==s[j] && re[i+1][j-1]==1)
                        {
                            re[i][j]=1; 
                        }
                    }
                }

                if(re[i][j]==1)
                {
                    cnt=cnt+1;
                }

            }
        }

        return cnt;

    }
};

128. 最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {

        int len=nums.size();
        if(len==0)
        {
            return 0;
        }
        if(len==1)
        {
            return 1;
        }

        sort(nums.begin(),nums.end());

        //中间结果
        int re=1;

        //返回结果
        int result=1;

        int temp=nums[0];

        for(int i=1;i<len;i++)
        {
            cout<<"nums[i][j]="<<nums[i]<<endl;
            if(nums[i]==temp+1)
            {
                re=re+1;
            }
            else if(nums[i]==temp)
            {
                //啥都不干
            }
            else
            {
                if(re>result)
                {
                    result=re;
                }
                re=1;
            }
            cout<<"re="<<re<<endl;
            cout<<"result="<<result<<endl;
            temp=nums[i];
            
        }

        if(re>result)
        {
            result=re;
        }

        return result;


    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值