贪心:
加油站
在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。
你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。
如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。
思路
如果总油量减去总消耗大于等于零那么一定可以跑完一圈,说明各个站点的加油站剩油量list[i]相加一定是大于等于零的。(加油站的剩余量 list[i]==gas[i] - cost[i]。)
i从0开始累加list[i],和记为sum,一旦sum小于零,说明[0, i]区间都不可能作为起始位置,因为这个区间选择任何一个位置作为起点,到i这里永远都会断油,那么起始位置需从i+1算起,再将sum重置为0计算sum。
如果出现更大的负数,利用循环会更新i,那么起始位置start又变成新的i+1了。
int sum=0;//记录局部和
int Sum=0;//记录总和
int start;//记录起始位置
int i;
for(i=0;i<n;i++){
sum+=gas[i] - cost[i];
Sum+=gas[i] - cost[i];
if(sum<0){
start=i+1;
sum=0;
}
}
if(Sum<0){//如果总和都小于零,那么就不可能跑完全程
retrun -1;
}
else return start;
分发糖果:
老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。
你需要按照以下要求,帮助老师给这些孩子分发糖果:
1.每个孩子至少分配到 1 个糖果。
2.相邻的孩子中,评分高的孩子必须获得更多的糖果。
那么这样下来,老师至少需要准备多少颗糖果呢?
思路
这道题目一定是要确定一边之后,再确定另一边,例如比较每一个孩子的左边,然后再比较右边(如果两边一起考虑一定会顾此失彼。)
初始化糖果数组carry,因为每个小朋友一定会有一个糖;
for(i=0;i<n;i++){
candy[i]=1;
}
先确定右边评分大于左边:
for(i=1;i<n;i++){
if(cnt[i]>cnt[i-1]){
candy[i]=candy[i-1]+1;
}
}
然后确定左边大于右边的情况
for(i=n-2;i>=0;i--){ / /为了利用之前右边大于左边得到的数据,我们需要从最后一个元素开始遍历;
if(cnt[i]>cnt[i+1]){
candy[i]=max(candy[i],candy[i+1]+1); / /取较大值,满足“即比左边大,也比右边大”;
}
}
最后将candy数组元素求总和。
链表:
struct no{
int data;
struct no *next;
}*head; // 这里的head为虚拟头节点。
反转链表:
将链表元素顺序反转。
注意点:
既然需要反转链表,就说明我们需要将每个元素的next指针指向转向。那么每次转向之前我们需要定义临时指针来储存下一个元素的地址,不然直接转换方向会丢失下一个元素的地址。
双指针法:
struct no *pre=head;
struct no *cur=head->next;
struct no temp=NULL; // 临时指针
while(cur!=NULL){ // 只要cur不为最后一个元素的next指向的NULL
temp=cur->next;
cur->next=pre;
pre=cur;
cur=temp;
}
return pre; // 返回pre是因为最后的pre即为链表的头指针
两两交换链表节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
struct no *cur = (struct no *)malloc(sizeof(struct no));
cur->next = head;
struct no *temp1;
steuct no *temp2;
while(cur->next && cur->next->next ){
temp1=cur->next;
temp2=cur->next->next->next;
cur->next=cur->next->next;
cur->next->next=temp1;
temp1->next=temp2;
cur=cur->next->next;
}