老师想给孩子们分发糖果,有 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;
}
};
给定一个整数 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);
}
}
};
给定一个整数数组 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
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 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->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
给定一个链表,判断链表中是否有环。
一、 假设链表中不存在环
快指针一定会走到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;
}
};
给定一个链表,删除链表的倒数第 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;
}
};
给定一个带有头结点 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;
}
};