刷题Leetcode

目录

1.按奇偶排序数组

2.从尾到头打印链表

3.替换空格

4.二维数组中的查找

5.六一儿童节

6.大整数相乘

7.最大乘积

8.两数之和

9.数组中重复的数字

10.二维数组中的查找

11. 最大矩形

12.跳跃游戏

13.三角形的最大周长

14.DI序列的有效排列

15.最佳买卖股票时机含冷冻期

16.连续数组

17.汉明距离

18.汉明距离总和


1.按奇偶排序数组

给定一个非负整数数组 A,返回一个由 A 的所有偶数元素组成的数组,后面跟 A 的所有奇数元素。

你可以返回满足此条件的任何数组作为答案。

示例:

输入:[3,1,2,4]

输出:[2,4,3,1]

输出 [4,2,3,1],[2,4,1,3] 和 [4,2,1,3] 也会被接受。

/**
 * Return an array of size *returnSize.
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* sortArrayByParity(int* A, int ASize, int* returnSize) {
    int temp,p=0,i;
    for(i=0;i<ASize;i++)
    {
        if(A[i]%2==0)
        {
            temp=A[i];
            A[i]=A[p];
            A[p]=temp;
            p++;
        }
    }
    *returnSize=ASize;
    return A;
}

2.从尾到头打印链表

输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> value;
        if(head != NULL)
        {
            value.insert(value.begin(),head->val);
            while(head->next != NULL)
            {
                value.insert(value.begin(),head->next->val);
                head = head->next;
            }         
              
        }
        return value;
    }
};

3.替换空格

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

 void replaceSpace(char *&str,int length) {
         char *newstr;int flag=0,i=0,j=0;
         for(i=0;i<length;i++)
             if(str[i]==' ') flag++;
        newstr=new char[length+flag*3];
        for(i=0,j=0;i<length;i++,j++)
            if(str[i]==' '){
                newstr[j]='%';
                newstr[j+1]='2';
                newstr[j+2]='0';
                j=j+2;
            }
           else
                newstr[j]=str[i];
        str=newstr;
         
    }

4.二维数组中的查找

在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int flag=array[0].size();
        for(int i=0;i<array.size();i++)
            for(int j=0;j<flag;j++)
            {
                if(target==array[i][j]) return true;
                if(target<array[i][j])
                {
                    flag=j;
                    break;
                }
            }
        return false;
    }
};

5.六一儿童节

六一儿童节,老师带了很多好吃的巧克力到幼儿园。每块巧克力j的重量为w[j],对于每个小朋友i,当他分到的巧克力大小达到h[i] (即w[j]>=h[i]),他才会上去表演节目。老师的目标是将巧克力分发给孩子们,使得最多的小孩上台表演。可以保证每个w[i]> 0且不能将多块巧克力分给一个孩子或将一块分给多个孩子。

#include<iostream>
#include<algorithm>
using namespace std;
 
int main(){
    int n,m;
    int *h,*w;
    cin>>n;
    h=new int[n];
    for(int i=0;i<n;i++){
        cin>>h[i];
    }
    cin>>m;
    w=new int[m];
    for(int j=0;j<m;j++){
        cin>>w[j];
    }
    sort(h, h+n); sort(w, w+m);
    int i = 0, j = 0, res = 0;
    while(j < m && i < n){
        if(h[i] <= w[j]) {res++; i++; j++;}
        else j++;
    }
    cout<<res<<endl;
}

6.大整数相乘

有两个用字符串表示的非常大的大整数,算出他们的乘积,也是用字符串表示。不能用系统自带的大整数类型。

#include<stdio.h>
#include<string>
#include<iostream>
using namespace std;
const int L=11000;
string mul(string,string);
int main(){
    string x,y;
    while(cin>>x>>y)
        cout<<mul(x,y)<<endl;
}
string mul(string a,string b) {
    string s;
    int na[L],nb[L],nc[L],La=a.size(),Lb=b.size(),i,j;
    fill(na,na+L,0);fill(nb,nb+L,0);fill(nc,nc+L,0);
    for(i=La-1;i>=0;i--) na[La-i]=a[i]-'0';
    for(i=Lb-1;i>=0;i--) nb[Lb-i]=b[i]-'0';
    for(i=1;i<=La;i++)
        for(j=1;j<=Lb;j++)
        nc[i+j-1]+=na[i]*nb[j];
    for(i=1;i<=La+Lb;i++)
        nc[i+1]+=nc[i]/10,nc[i]%=10;
    if(nc[La+Lb]) s+=nc[La+Lb]+'0';
    for(i=La+Lb-1;i>=1;i--)
        s+=nc[i]+'0';
    return s;
}

7.最大乘积

给定一个无序数组,包含正数、负数和0,要求从中找出3个数的乘积,使得乘积最大。

要求时间复杂度:O(n),空间复杂度:O(1)

#include<iostream>
using namespace std;
 
int main()
{
    long long *a,c,d,result,temp,max,pre,ppre;
    int i,n;
    cin>>n;
    a=new long long[n];
    for(i=0;i<n;i++)
    {
        cin>>a[i];
    }
    for(int j=0;j<n;j++)
    {
    for(i=0;i<n-j-1;i++)
    {
        if(a[i]>a[i+1])
        {
            temp=a[i];
            a[i]=a[i+1];
            a[i+1]=temp;
        }
    }
    }
    max=a[n-1];
    pre=a[n-2];
    ppre=a[n-3];
    for(int j=0;j<n;j++)
    {
    for(i=0;i<n-j-1;i++)
    {
        if(a[i]<a[i+1])
        {
            temp=a[i];
            a[i]=a[i+1];
            a[i+1]=temp;
        }
    }
    }
    c=max*pre*ppre;
    d=a[n-1]*a[n-2]*max;
    if(c>d)
    cout<<c<<endl;
    else
    cout<<d<<endl;
}

8.两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* twoSum(int* nums, int numsSize, int target) {
    static int a[2];
    int temp;
    for(int p=0;p<numsSize-1;p++)
    {
        temp=target-nums[p];
        for(int q=p+1;q<numsSize;q++)
        {
            if(nums[q]==temp)
            {
                a[0]=p;a[1]=q; return a;
            }   
        }
    }
    return 0;
}

9.数组中重复的数字

在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复几次。请找出数组中任意一个重复的数字。

Input: {2, 3, 1, 0, 2, 5}

Output: 2

要求是时间复杂度 O(N),空间复杂度 O(1)。

因此不能使用排序的方法,也不能使用额外的标记数组。

//对于这种数组元素在 [0, n-1] 范围内的问题,可以将值为 i 的元素调整到第 i 个位置上进行求解。
bool Solution(int* nums, int length, int* duplication){
    for (int i = 0; i < length; i++) {
        while (nums[i] != i) {
            if (nums[i] == nums[nums[i]]) {
                duplication[0] = nums[i];
                cout<<duplication[0];
                return true;
            }
            swap(nums[i],nums[nums[i]]);
        }
    }
    return false;
}

int main(){
    int arr[6] = {2, 3, 1, 0, 2, 5};
    int *b=new int[6];
    Solution(arr,6,b);
}

10.二维数组中的查找

给定一个二维数组,其每一行从左到右递增排序,从上到下也是递增排序。给定一个数,判断这个数是否在该二维数组中。要求时间复杂度 O(M + N),空间复杂度 O(1)

//二维数组中的查找.该二维数组中的一个数,它左边的数都比它小,下边的数都比它大。因此,从右上角开始查找.
bool Find(int target, int matrix[5][5],int rows,int cols) {
    int r = 0, c = cols - 1; // 从右上角开始
    while (r <= rows - 1 && c >= 0) {
        if (target == matrix[r][c])
            return true;
        else if (target > matrix[r][c])
            r++;
        else
            c--;
    }
    return false;
}
int main(){
    int arr[5][5] = {{1,   4,  7, 11, 15},
                     {2,   5,  8, 12, 19},
                     {3,   6,  9, 16, 22},
                     {10, 13, 14, 17, 24},
                     {18, 21, 23, 26, 30}};
    int target;
    while(cin>>target){
        if(Find(target,arr,5,5))
        cout<<"True!"<<endl;
    else
        cout<<"False!"<<endl;
    }
}

 

11. 最大矩形

给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

示例:

输入:
[
  ["1","0","1","0","0"],
  ["1","0","1","1","1"],
  ["1","1","1","1","1"],
  ["1","0","0","1","0"]
]
输出: 6

class Solution {
public:
    int maximalRectangle(vector<vector<char>>& matrix) {
       int m = matrix.size();
        if(!m) return 0;
        int n = matrix[0].size();
        vector<int> dp(n + 1,0);
        dp[n] = -1;
        int res = 0;
        stack<int> s;
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++)
                if(matrix[i][j] == '1') dp[j] += 1;
                else dp[j] = 0;
            for(int j = 0;j <= n;j++){
                while(!s.empty() && dp[s.top()] > dp[j]){
                    auto t = s.top();
                    s.pop();
                    int pre = -1;
                    if(!s.empty()) pre = s.top();
                    res = max(res,dp[t] * (j !=n ? (j - pre - 1) :(n - pre - 1)));
                }
                if(j == n) break;
                s.push(j);
            }
        }
        return res;
    }
};

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

递归问题:http://39.96.217.32/blog/4

12.跳跃游戏

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

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

判断你是否能够到达最后一个位置。

例一:输入: [2,3,1,1,4] 输出: true 解释: 从位置 0 到 1 跳 1 步, 然后跳 3 步到达最后一个位置

例二:输入: [3,2,1,0,4] 输出: false 解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。

class Solution {
public:
    bool canJump(vector<int>& nums) {
        if(nums.size() == 1) {
            return true;
        }
        int n = -2; 
        for(int i=nums.size() - 2;i>=0;i--) {
             // 从后往前找,把当前过不了的坑的位置记录起来
            if(nums[i] == 0 && n<=-1) {  
                // 如果遇到新的坑并且当前没有坑,则记录坑的位置
                n = i;
                continue;
            }
            if(n>=0 && nums[i] > (n-i)) {   
            // 如果发现元素的值大于元素和坑的距离,说明可以跳过这个坑,将坑的下标置为-1,继续往前找坑
                n = -1;
            }
        }
        // 走到起点发现没有记录到坑,说明可以跳过去,否则返回false
        return n<0;
    }
};

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

13.三角形的最大周长

给定由一些正数(代表长度)组成的数组 A,返回由其中三个长度组成的、面积不为零的三角形的最大周长。

如果不能形成任何面积不为零的三角形,返回 0

输入:[2,1,2] 输出:5

输入:[1,2,1] 输出:0

输入:[3,2,3,4] 输出:10

class Solution {
    public int largestPerimeter(int[] A) {
        Arrays.sort(A);
        if(A.length<3)
            return 0;
        for(int i = A.length - 1; i >= 2; i--) {
            int a = A[i];
            int b = A[i - 1];
            int c = A[i - 2];
            if(a < b + c){
                return a + b + c;
            }
        }
        return 0;
    }
}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

14.DI序列的有效排列

我们给出 S,一个源于 {'D', 'I'} 的长度为 n 的字符串 。(这些字母代表 “减少” 和 “增加”。)
有效排列 是对整数 {0, 1, ..., n} 的一个排列 P[0], P[1], ..., P[n],使得对所有的 i

  • 如果 S[i] == 'D',那么 P[i] > P[i+1],以及;
  • 如果 S[i] == 'I',那么 P[i] < P[i+1]

有多少个有效排列?因为答案可能很大,所以请返回你的答案模 10^9 + 7.

输入:"DID" 输出:5 解释: (0, 1, 2, 3) 的五个有效排列是: (1, 0, 3, 2) (2, 0, 3, 1) (2, 1, 3, 0) (3, 0, 2, 1) (3, 1, 2, 0)

class Solution {
public:
    int numPermsDISequence(string S) {
        int M = pow(10, 9)+7;
        //第一维表示取到S的第几个字母,第二维表示取值,例如0,1,2,3,dp[i][3]结尾取3
        vector<vector<int>> dp(S.size()+1,vector<int>(S.size()+1,0));
        dp[0][0] = 1;
        for(int i = 0;i<S.size();i++){
            if(S[i] == 'I'){
                for(int j = 1;j<=i+1;j++){
                    dp[i+1][j] = (dp[i+1][j-1]+dp[i][j-1])%M;
                }
            }else{
                for(int j = i;j>=0;j--){
                    dp[i+1][j] = (dp[i+1][j+1]+dp[i][j])%M;
                }
            }
        }
        int res = 0;
        for(int i = 0;i<dp.size();i++){
            res=(res+dp[dp.size()-1][i])%M;
        }
        return res;
    }
};

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

15.最佳买卖股票时机含冷冻期

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

  • 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

输入: [1,2,3,0,2] 输出: 3 解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

'''
sell[i]表示截至第i天,最后一个操作是卖时的最大收益;
buy[i]表示截至第i天,最后一个操作是买时的最大收益;
cool[i]表示截至第i天,最后一个操作是冷冻期时的最大收益;
递推公式:
sell[i] = max(buy[i-1]+prices[i], sell[i-1]) (第一项表示第i天卖出,第二项表示第i天冷冻)
buy[i] = max(cool[i-1]-prices[i], buy[i-1]) (第一项表示第i天买进,第二项表示第i天冷冻)
cool[i] = max(sell[i-1], buy[i-1], cool[i-1])
'''
class Solution:
    def maxProfit(self, prices):
        n = len(prices)
        if n == 0:
            return 0     
        sell = [0 for _ in range(n)]
        buy = [0 for _ in range(n)]
        cool = [0 for _ in range(n)]
        buy[0] = -prices[0]
        for i in range(1,n):
            sell[i] = max(buy[i-1] + prices[i], sell[i-1])
            buy[i] = max(cool[i-1] - prices[i], buy[i-1])
            cool[i] = max(sell[i-1], buy[i-1],cool[i-1])
        return sell[n-1]

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

   /**
     * buy[i]表示第i天买入时的最大利润(最后一个操作是买)
     * sell[i]表示第i天卖出时的最大利润(最后一个操作是卖)
     */
    public int maxProfit(int[] prices) {
        int n = prices.length;
        if (n == 0)
            return 0;
        int[] buy = new int[n];
        int[] sell = new int[n];
        buy[0] = -prices[0];
        sell[0] = 0;
        if (n > 1) {
            buy[1] = Math.max(buy[0], 0 - prices[1]);//因为冷冻期,所以前一天只能为买,所以比较的是buy[0]=-prices[0],而大前天无买卖,所以利润为0,则得到0-prices[1]
            sell[1] = Math.max(sell[0], buy[0] + prices[1]);
        }
        for (int i = 2; i < n; ++i) {
            buy[i] = Math.max(buy[i - 1], sell[i - 2] - prices[i]);//因为冷冻期,所以前一天只能为买,所以比较的是buy[i - 1]
            sell[i] = Math.max(sell[i - 1], buy[i - 1] + prices[i]);//比较的是前一天卖出的最大利润和前一天买入的最大利润+今天卖出的价格
        }
        return sell[n - 1];
    }

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

16.连续数组

给定一个二进制数组, 找到含有相同数量的 0 和 1 的最长连续子数组(的长度)。

输入: [0,1] 输出: 2 说明: [0, 1] 是具有相同数量0和1的最长连续子数组。

输入: [0,1,0] 输出: 2 说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。

class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        map<int,int> m;
        int sum = 0;
        int res = 0;
        for(int i = 0;i<nums.size();i++){
            sum+=(nums[i]==1?1:-1);
            if(sum == 0){
                res = i+1;
            }
            else{
                if(m[sum]==0){
                    m[sum] = i+1;
                }else{
                    res = max(res,i-m[sum]+1);
                }
            }
        }
        return res;
    }
};

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

17.汉明距离

两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目。

给出两个整数 xy,计算它们之间的汉明距离。

输入: x = 1, y = 4 输出: 2

解释: 1 (0 0 0 1)

         4 (0 1 0 0)

                ↑    ↑ 上面的箭头指出了对应二进制位不同的位置。

方法一:

class Solution {
public:
    int hammingDistance(int x, int y) {
        return bitset<32>(x ^ y).count();
    }
};
//bitset<32> bv; 声明 bv 是 32位2进制 bitset class 的对象。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

方法二:

class Solution {
    public int hammingDistance(int x, int y) {
        int sum = 0;
        x = x^y;
        while(x!=0) {
            sum+=x&1;
            x>>=1;
        }
        return sum;
    }

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

18.汉明距离总和

两个整数的 汉明距离 指的是这两个数字的二进制数对应位不同的数量。

计算一个数组中,任意两个数之间汉明距离的总和。

输入: 4, 14, 2 输出: 6 解释: 在二进制表示中,4表示为0100,14表示为1110,2表示为0010。(这样表示是为了体现后四位之间关系) 所以答案为: HammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) = 2 + 2 + 2 = 6.

class Solution {
public:
    int totalHammingDistance(vector<int>& nums) {
        int res = 0,n = nums.size();
        for(int i=0;i<32;i++){
            int cnt = 0;
            for(auto num:nums){
                if(num & (1<<i)) cnt++;//统计第i位上1的个数
            }
            res += cnt * (n-cnt);//每一位0的个数与1的个数相乘
        }
        return res;
    }
};

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

class Solution {
    public int totalHammingDistance(int[] nums) {
        int total = 0;
    	for(int i = 0; i < 32; i++) {
    		int distance = 0;
    		for(int j = 0; j < nums.length; j++) {
    			if((nums[j] & (1 << i - 1)) != 0)
    				distance++;
    		}
    		total += distance*(nums.length - distance);
    	}
    	return total;
    }
}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值