leetcode题解日练--2016.7.24

日练三题,冰冻三尺非一日之寒。

今日题目:

1、划分链表; | tag:链表、两指针

2、唯一路径II; |tag:数组、DP

3、电话号码组合。 |tag:字符串、回溯

4、二叉树ZigZag层次遍历 | tag:树、BFS、栈

今日摘录:

你不愿意种花,你说,我不愿看见它一点点凋落。是的,为了避免结束,你避免了一切开始。
《避免》

86. Partition List | Difficulty: Medium

Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.

You should preserve the original relative order of the nodes in each of the two partitions.

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

tag:链表、两个指针
题意:将链表中小于value的元素放到前面,大于等于value的元素放在后面并保持原来的顺序。

思路:
1、开始以为是快排的partition,后面发现不是那个意思。通俗理解为按照 x < value 将一部分元素筛选出来,并且保持剩下元素相对位置不变,然后将挑选出来的最后元素和剩下元素的第一个元素连起来。形成我们最终需要的最终链表。我的思路是创建两个指针分别存小的元素和大的元素,最后再拼接。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode*cur=head,*next=NULL;
        ListNode *smallHead = new ListNode (INT_MIN);
        ListNode *small = smallHead;
        ListNode *largeHead = new ListNode (INT_MIN);
        ListNode *large = largeHead;
        while(cur)
        {
            next = cur->next;
            if(cur->val<x)
            {
                small->next = cur;
                small = small->next;
                small->next = NULL;
                cur = next;
            }
           else
           { 
             large->next = cur;
             large = large->next;
             large->next = NULL;
            cur = next;
           }

        }
        small->next = largeHead->next;
        return smallHead->next;
    }
};

结果:8ms

2、发现一个同样的思路,我怎么就写得这么丑,于是仿照别人自己重新写了一遍,终于好看多了。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode node1(0),node2(0);
        ListNode *p1 = &node1,*p2 = &node2;
        while(head)
        {
            if(head->val<x)
            {
                p1->next = head;
                p1 = p1->next;
            }
            else
            {
                p2 ->next = head;
                p2 = p2->next;
            }
            head = head->next;
        }
        p1->next = node2.next;
        p2->next = NULL;
        return node1.next;
    }
};

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

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {

        ListNode *lessHead = new ListNode(INT_MIN),*greatHead = new ListNode(INT_MIN);
        ListNode *less = lessHead,*great = greatHead;

        ListNode*node = head;
        while(node)
        {
            if(node->val < x)   {less->next = node;less = less->next;}
            else    {great->next = node;great = great->next;}
            node = node->next;
        }
        less->next = greatHead->next;
        great->next = NULL;
        return lessHead->next;
    }
};

结果:9ms

63. Unique Paths II | Difficulty: Medium

Follow up for “Unique Paths”:

Now consider if some obstacles are added to the grids. How many unique paths would there be?

An obstacle and empty space is marked as 1 and 0 respectively in the grid.

For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.

[
[0,0,0],
[0,1,0],
[0,0,0]
]
The total number of unique paths is 2.

Note: m and n will be at most 100.

tag: 数组|DP
相关题目:Unique Path
题意:与那道求唯一路径数的题目非常类似,唯一的区别在于其中增加了一些障碍点,这些障碍点是走不通的。

思路:
1、与当时在求唯一路径数的时候情况很类似,是首先将第0行和第0列初始化为1,因为这边只有一种情况的存在,然后从第1行第1列的元素开始计算,每个值都是它左边的dp值和上面的dp值之和。
那么这里的区别在什么地方呢?在求dp[i][j]的时候,需要判断obstacleGrid[i][j]的值,也就是求到一个点的路径数,需要预先判断一下这个点能不能走,能走才加其左和上。
先用mn的时间复杂度和空间复杂度做一遍。

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int rows = obstacleGrid.size(),cols = obstacleGrid[0].size();
        vector<vector<int>> dp(rows+1,vector<int>(cols+1,0));
        dp[1][0] = 1;
        for(int i=1;i<=rows;i++)
        {
            for(int j=1;j<=cols;j++)
            {
                if(!obstacleGrid[i-1][j-1])     dp[i][j]+=dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[rows][cols];
    }
};

结果:4ms

2、很类似unique path题,这里也能优化空间到o(min(m,n)),这里懒得设置新的接口,所以就任选m或者n来实现。

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int rows = obstacleGrid.size(),cols = obstacleGrid[0].size();
       vector<int> dp(rows,0);
        for(int i=0;i<rows;i++)
        {
            if(!obstacleGrid[i][0]) dp[i]=1;
            else    break;
        }
        for(int i=1;i<cols;i++)
        {
            if(dp[0] && !obstacleGrid[0][i]) dp[0]=1;
            else    dp[0]=0;
            for(int j=1;j<rows;j++)
            {
                if(!obstacleGrid[j][i])     
                {
                    dp[j]+=dp[j-1];
                }
                else    dp[j]=0;
            }
        }
        return dp[rows-1];
    }
};

结果:4ms

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int rows = obstacleGrid.size(),cols = obstacleGrid[0].size();
       vector<int> dp(rows,0);
        for(int i=0;i<rows;i++)
        {
            if(!obstacleGrid[i][0]) dp[i]=1;
            else    break;
        }
        for(int i=1;i<cols;i++)
        {
            bool flag = false;
            if(dp[0] && !obstacleGrid[0][i]) {dp[0]=1;flag=true;}
            else    dp[0]=0;
            for(int j=1;j<rows;j++)
            {
                if(!obstacleGrid[j][i])     
                {
                    dp[j]+=dp[j-1];
                    flag = true;
                }
                else    dp[j]=0;
            }
            if(!flag)   return 0;
        }
        return dp[rows-1];
    }
};

结果:4ms
还可以在每次赋值的时候加一次条件判断,如果某一列全部都是0,那么就可以提前终止。

17. Letter Combinations of a Phone Number |Difficulty: Medium

Given a digit string, return all possible letter combinations that the number could represent.

A mapping of digit to letters (just like on the telephone buttons) is given below.

Input:Digit string “23”
Output: [“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].

tag:数组、回溯
题意:给一个电话号码,每个按键上面都对应几个字母,求所有可能的字母组合

思路:
1、直接模拟一下”23”这种情况下是如何生成结果的
首先访问2,这里有3种情况,a、b、c,对于每个字母,后面又进来一个3,这个时候对于a、b、c三种情况,每一种都对应了d、e、f三中情况,组合起来就
是9种情况。

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        string charmap[10] = {"0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
        vector<string>res;
        if(digits.size()==0) return res;
        res.push_back("");
        int length = digits.size();
        for(int i=0;i<length;i++)
        {
            vector<string> tmp;
            string chars = charmap[digits[i] - '0'];
            for(int c=0;c<chars.size();c++)
            {
                for(int j=0;j<res.size();j++)
                    tmp.push_back(res[j]+chars[c]);
            }
            res = tmp;
        }
        return res;
    }
};

结果:0ms
输入:”36” 输出:[“dm”,”em”,”fm”,”dn”,”en”,”fn”,”do”,”eo”,”fo”]

2、如果希望输出格式类似回溯顺序,即aaa、aab、aac、aba、abb……等等,应该使用如下思路

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        string charmap[10] = {"0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
        vector<string>res;
        if(digits.size()==0) return res;
        res.push_back("");
        int length = digits.size();
        for(int i=0;i<length;i++)
        {
            while(res.front().size()==i)
            {
                string tmp = res.front();
                res.erase(res.begin());
                for (auto c : charmap[digits[i]-'0'])
                {
                    res.push_back(tmp+c);
                }
            }
        }
        return res;
    }
};

结果:0ms
输入:“36” 输出:[“dm”,”dn”,”do”,”em”,”en”,”eo”,”fm”,”fn”,”fo”]

103. Binary Tree Zigzag Level Order Traversal | Difficulty: Medium

Given a binary tree, return the zigzag level order traversal of its nodes’ values. (ie, from left to right, then right to left for the next level and alternate between).

For example:
Given binary tree [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
return its zigzag level order traversal as:
[
[3],
[20,9],
[15,7]
]

tag:树、BFS、栈
题意:给一棵树,用zigzag层次遍历的方法去遍历这棵树。
思路:
1、很显然,用两个栈或者队列可以实现这个功能,这里以栈为例。每次访问一层,我们就在其中的一个栈中去访问元素,直到这层访问完毕就去访问剩下的那个栈。那么如何控制从左到右和从右到左之间的切换呢?这个时候可以设置一个标志位,每次换层的时候切换一下标志位就可以了。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int> > res;
        if(!root)   return res;
        stack<TreeNode*> nodes[2];
        int flag = 0;
        nodes[flag].push(root);
        vector<int> level;
        while(!nodes[flag].empty())
        {
            TreeNode* tmp = nodes[flag].top();
            nodes[flag].pop();
            level.push_back(tmp->val);
            if(flag)
            {
                if(tmp->right)  nodes[1-flag].push(tmp->right);
                if(tmp->left)   nodes[1-flag].push(tmp->left);
            }
            else
            {
                if(tmp->left)   nodes[1-flag].push(tmp->left);
                if(tmp->right)  nodes[1-flag].push(tmp->right);
            }
            if(nodes[flag].empty())
            {
                res.push_back(level);
                level.clear();
                flag = 1-flag;
            }
        }
        return res;
    }
};

结果:4ms

2、可以再做一些优化,只用一个队列加上一个标志位

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int> > res;
        if(!root)   return res;
        queue<TreeNode*> nodes;
        bool LeftToRight = true;
        nodes.push(root);
        while(!nodes.empty())
        {
            int size = nodes.size();
            vector<int> level(size);
            for(int i=0;i<size;i++)
            {
                TreeNode* tmp = nodes.front();
                nodes.pop();
                int index = (LeftToRight)?i:size-1-i;
                level[index] = tmp->val;
                if(tmp->left) nodes.push(tmp->left);
                if(tmp->right) nodes.push(tmp->right);
            }
            LeftToRight = !LeftToRight;
            res.push_back(level);
        }
        return res;
    }
};

结果:6ms

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值