2020年1.17-1.27leetcode刷题笔记

leetcode刷题记录

1.17

135 困难 分发糖果

题目描述

老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。

你需要按照以下要求,帮助老师给这些孩子分发糖果:

每个孩子至少分配到 1 个糖果。
相邻的孩子中,评分高的孩子必须获得更多的糖果。
那么这样下来,老师至少需要准备多少颗糖果呢?

示例 1:

输入: [1,0,2]
输出: 5
解释: 你可以分别给这三个孩子分发 2、1、2 颗糖果。
示例 2:

输入: [1,2,2]
输出: 4
解释: 你可以分别给这三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这已满足上述两个条件。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/candy
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

从左侧进行挨个比较 遇到比左侧大的 令其糖果数为左侧糖果数+1
从右侧向左挨个进行比较 遇到比右侧大的且糖果数没有大于右侧的 令其糖果数为右侧糖果数目+1

第二次比较挨个加入总数 节约时间

解题代码
class Solution {
public:
    int candy(vector& ratings) {
        int size=ratings.size();
        vector sm(size,1);
        int sum=0;
        for(int i=1;i=0;i--){
            if (ratings[i]>ratings[i+1]&&(sm[i]<=sm[i+1]))
            {
                sm[i]=sm[i+1]+1;
            }
            sum+=sm[i];
        }
        sum+=sm[size-1];
        return sum;
    }
};

386 中等 字典序排数

题目描述

给定一个整数 n, 返回从 1 到 n 的字典顺序。

例如,

给定 n =1 3,返回 [1,10,11,12,13,2,3,4,5,6,7,8,9] 。

请尽可能的优化算法的时间复杂度和空间复杂度。 输入的数据 n 小于等于 5,000,000。

解题思路

下面是[1,10]的结果
[1,10,2,3,4,5,6,7,8,9]
下面是[1,100]的结果

[1,10,100,11,12,13,14,15,16,17,18,19,2,20,21,22,23,24,25,26,27,28,29,3,30,31,32,33,34,35,36,37,38,39,4,40,41,42,43,44,45,46,47,48,49,5,50,51,52,53,54,55,56,57,58,59,6,60,61,62,63,64,65,66,67,68,69,7,70,71,72,73,74,75,76,77,78,79,8,80,81,82,83,84,85,86,87,88,89,9,90,91,92,93,94,95,96,97,98,99]

下面是[1,1000]的结果

[1,10,100,1000,101,102,103,104,105,106,107,108,109,11,110,111,112,113,114,115,116,117,118,119,12,120,121,122,123,124,125,126,127,128,129,13,130,131,132,133,134,135,136,137,138,139,14,140,141,142,143,144,145,146,147,148,149,15,150,151,152,153,154,155,156,157,158,159,16,160,161,162,163,164,165,166,167,168,169,17,170,171,172,173,174,175,176,177,178,179,18,180,181,182,183,184,185,186,187,188,189,19,190,191,192,193,194,195,196,197,198,199,2,20,200,201,202,203,204,205,206,207,208,209,21,210,211,212,213,214,215,216,217,218,219,22,220,221,222,223,224,225,226,227,228,229,23,230,231,232,233,234,235,236,237,238,239,24,240,241,242,243,244,245,246,247,248,249,25,250,251,252,253,254,255,256,257,258,259,26,260,261,262,263,264,265,266,267,268,269,27,270,271,272,273,274,275,276,277,278,279,28,280,281,282,283,284,285,286,287,288,289,29,290,291,292,293,294,295,296,297,298,299,3,30,300,301,302,303,304,305,306,307,308,309,31,310,311,312,313,314,315,316,317,318,319,32,320,321,322,323,324,325,326,327,328,329…

下面是[1,10000]的结果

[1,10,100,1000,10000,1001,1002,1003,1004,1005,1006,1007,1008,1009,101,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,102,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,103,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,104,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,105,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,106,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,107,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,108,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,109,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,11,110,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,111,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,112,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,113,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,114,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,115,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,116,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,117,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,118,1180,1181…

将上面的过程进行抽象就是:

起始我们放置[1,9]
    |放置1,我们放置[10,19],递归
    |	放置[10,19]
    |		|首先放置10,然后放置[100, 109],递归
    |		|	放置[100,109]
    |		|		|放置100,然后放置[1000,1009],递归
    |		|		|放置101,然后放置[1010,1019],递归
    |		|		|.
    |		|		|放置109,然后放置[1090,1099],递归
    |		|
    |		|然后放置11,再放置[110, 119],递归
    |		|.
    |		|最后放置19,再放置[190, 199],递归
    |接着放置2,然后放置[20, 29],递归
    |接着放置3,然后放置[30, 39],递归
    |接着放置4,然后放置[40, 49],递归
    |.
    |接着放置9,然后放置[90, 99],递归
解题代码
class Solution {
public:
    vector result;
    vector lexicalOrder(int n) {
        mydfs(n,0);
        return result;
    }

    void mydfs(int n,int lastnum){
        int nownum=lastnum*10;

        if(nownum!=0&&nownum<=n){
            result.push_back(nownum);
            mydfs(n,nownum);
        }

        for(int index=1;index<10&&nownum+index<=n;index++){
            result.push_back(nownum+index);
            mydfs(n,nownum+index);
        }
    }
};

1 简单 两数之和

题目描述

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

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

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

熟悉vector的用法

解题代码
class Solution {
public:

    vector twoSum(vector& nums, int target) {
        vector r;
        
        for(int i=0;i

2 中等 两数相加

题目描述

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

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

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

ListNode的使用
需要新建指针 不使用原指针
使用?:运算符
(判断语句)?情况真:情况假

解题代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* h=new ListNode(-1);
        ListNode *p1=l1,*p2=l2,*p3=h;
        int jw=0;

        while(p1!=nullptr||p2!=nullptr){
            int x=(p1!=nullptr)?p1->val:0;
            int y=(p2!=nullptr)?p2->val:0;
            int rs=(x+y+jw)%10;
            jw=(x+y+jw)/10;
            p3->next=new ListNode(rs);
            p3=p3->next;
            if(p1!=nullptr){
                p1=p1->next;
            }
            if(p2!=nullptr){
                p2=p2->next;
            }
        }
        if(jw==1){
            p3->next=new ListNode(1);
        }
        return h->next;
    }
};

1.27

206 简单 反转链表

题目描述

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

解题思路

无需创建头结点 直接代入

解题代码
/*
 * @lc app=leetcode.cn id=206 lang=cpp
 *
 * [206] 反转链表
 */

// @lc code=start
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
       ListNode* hhead=NULL;
       ListNode* t=head;
       
       while (head!=NULL)
       {
           
           t=head;
           head=head->next;
           t->next=hhead;
           hhead=t;
       }
       return hhead;

    }
};
// @lc code=end


141 简单 环形链表

题目描述

给定一个链表,判断链表中是否有环。

解题思路

一、 假设链表中不存在环
快指针一定会走到NULL,直接return 0 即可

二、 假设链表中存在环
快指针 和 慢指针 一定会进入环,无论快慢指针何时进入环,中间相隔任意个节点,总会在某一次移动后相遇, fast == slow 时候返回 1

解题代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode *fast=head;
        ListNode *slow=head;
        while(fast!=NULL){
            if(fast->next!=NULL&&fast->next->next!=NULL){
                fast=fast->next->next;
                slow=slow->next;
            }else{
                return 0;
            }
            if(fast==slow){
                return 1;
            }
        }
        return 0;
    }
};

19 中等 删除链表的倒数第N个节点

题目描述

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

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:

给定的 n 保证是有效的。

解题思路

先前进N-1格 再边记录边前进

解题代码
/**
 * 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) {
        ListNode *hhead=head;
        
        ListNode *temp=head;
        for(int i=0;inext;
        }
        if(head->next==NULL){
            return hhead->next;
        }
        head=head->next;
        ListNode* pre=temp;
        temp=temp->next;
        while(head->next!=NULL){
            head=head->next;
            pre=temp;
            temp=temp->next;
        }
        pre->next=temp->next;
        return hhead;
    }
};

876 简单 链表的中间结点

题目描述

给定一个带有头结点 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

示例 1:

输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
示例 2:

输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。

解题思路

先统计长度 再除2

解题代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        int i=1;
        ListNode *hhead=head;
        while(head->next!=NULL)
        {
            head=head->next;
            i++;   
        }
        for(int j=0;jnext;
        }
        return hhead;
    }
};

你可能感兴趣的:(leetcode,算法,数据结构,leetcode)