leetcode题解日练--2016.8.10

###不给自己任何借口

今日题目:

1、加油站 ; tag:贪心

2、删除有序链表的重复元素II tag:链表

今日摘录:

如果你非要拒绝我,请不要那么绝对。因为你的一句“我没有那么喜欢你”,我都可以解读为“我有一点喜欢你。

——沈煜伦

134. Gas Station | Difficulty: Medium

There are N gas stations along a circular route, where the amount of gas at station i is gas[i].

You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations.

Return the starting gas station’s index if you can travel around the circuit once, otherwise return -1.

Note:
The solution is guaranteed to be unique.

tag:贪心
题意:在一个环路上有N个加油站,每一个加油站都有gas[i]的油,并且去下一个加油站都需要话费cost[i],如果能走通就返回出发点的坐标,如果不能就返回-1.

思路:
1、这道题还好,不算难,理清楚思路就很简单了。因为有N个加油站和N条路,所以可以将每一个加油站和每一条路都一一对应起来,第一步判断总油量是否大于总耗油,如果这个不能满足说明一定是到不了的。然后逐个位置去判断,思路有点类似最长子序列和,大概就是如果当前点出发去下一个点剩下的油量如果小于0(即在半路会没油),当前点就不可能是出发点,就将总油量置0,继续找出发点。如果到达点油量大于0,说明这段路可以走,这个时候将目前油量更新为到达点油量。如果出发前油量是0,那么这个点就是出发点。

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        vector<int>res(gas.size(),0);
        int index = -1;
        int sum = 0;
        for(int i=0;i<gas.size();i++)
        {
            res[i] = gas[i]-cost[i];
            sum+=res[i];
        }
        if(sum<0)   return -1;
        sum=0;
        for(int i=0;i<res.size();i++)
        {
            int reach = sum+res[i];
            if(reach<0)
                sum=0;
            else if (sum==0)
            {
                sum = reach;
                index = i;
            }
            else
            {   
                sum = reach;
            }
        }
        return index;
    }
};

结果:8ms

2、思路一样,看了下https://discuss.leetcode.com/topic/1344/share-some-of-my-ideas/2的解法,明显聪明很多,学习了

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int start=0,tank = 0,total=0;
        for(int i=0;i<gas.size();i++)
        {
            if((tank = tank+gas[i]-cost[i])<0)
            {
                start = i+1;
                total +=tank;
                tank = 0;
            }
        }
        return (total+tank<0)?-1:start;
    }
};

结果:8ms

82. Remove Duplicates from Sorted List II | Difficulty: Medium

Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.

For example,
Given 1->2->3->3->4->4->5, return 1->2->5.
Given 1->1->1->2->3, return 2->3.

相关题目:Remove Duplicates from Sorted List
tag:链表
题意:将一个有序链表中的所有重复元素删除(Remove Duplicates from Sorted List是所有重复元素保留一个)

思路:
第一步找到整个链表的头
第二步循环去判断链表中间的元素是否存在重复的,利用一个prev来保存之前尚未存在存在的子链表的尾部,flag来判断是否出现过重复的元素
第三步判断链表的尾部是否重复元素

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(!head || !head->next)   return head;
        bool flag = false;
        //找到头在什么位置
        while(head)
        {
            if(head->next && head->next->val==head->val)
                {head = head->next;flag = true;}
            else
            {
                if(flag)    {head = head->next;flag = false;}
                else    break;
            }
        }
        ListNode*pNode = head;
        ListNode*prev = NULL;
        flag = false;
        //遍历节点
        while(pNode)
        {
            //如果有下一个并且下一个节点不等于当前节点
            if(pNode->next&& pNode->next->val != pNode->val)   
            {
                //这里找到的是值有变化的位置,这里又有两种情况,第一种情况是没有出现连续重复值,直接prev和pNode都往后就行了
                if(!flag)
                {
                prev = pNode;
                pNode = pNode->next;
                }
                //第二种情况是之前出现过连续重复值值,需要把这些连续值都删除,并将flag还原成false
                else
                {
                    prev->next = pNode->next;
                    pNode = pNode->next;
                    flag = false;
                }
            }
            //下一个节点等于当前节点
            else
            {
                //这里都是值不变的可能性,又分了两种情况
                //第一种情况还没到底,置flag为true,继续往后访问
                if(pNode->next)
                {
                    pNode = pNode->next;
                    flag = true;
                }
                //第二种情况是到底了,如果出现了连续重复值,之前将最后一个非重复节点当成最后节点
                else
                {
                    if(flag) prev->next = NULL;
                    pNode = pNode->next;
                }
            }
        }

        return head;
    }
};

结果:12ms

2、递归版本,把逻辑理清代码很简单

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(!head)   return NULL;
        if(!head->next) return head;
        int val = head->val;
        ListNode*p = head->next;
        if(head->next->val != val)
        {
            head->next = deleteDuplicates(head->next);
            return head;
        }
        else
        {
            while(p && p->val == val)  p = p->next;
            return deleteDuplicates(p);
        }
    }
};

结果:8ms
update:2016.9.16
第二次刷代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(!head || !head->next)    return head;
        int val;
        ListNode*newHead = head;
        while(newHead->next)
        {
            if(newHead->next->val == newHead->val)
                {
                    int val = newHead->val;
                    while(newHead && newHead->val ==val)   newHead = newHead->next;
                    if(!newHead)    return newHead;

                }
            else    
                break;
        }
        ListNode *pre = newHead,*cur = newHead;
        while(cur)
        {
            if(cur->next )   
            {
                if(cur->val!=cur->next->val)
                {
                    pre = cur;
                    cur = cur->next;
                }
                else    
                {
                    val = cur->val;
                    while(cur && cur->val==val)    cur = cur->next;
                    pre->next = cur;
                }
            }
            else
            {
                if(cur->val==val)   pre->next=NULL;
                cur = cur->next;
            }
        }
        return newHead;
    }
};

结果:9ms

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值