Leetcode题解<五>

算法分析与设计课后作业

Posted by tomylee on December 26, 2017

No.1

题目链接:Gray Code

  • 题目描述:

    The gray code is a binary numeral system where two successive values differ in only one bit.

    Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0.

    For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:

    00 - 0
    01 - 1
    11 - 3
    10 - 2
    

    Note: For a given n, a gray code sequence is not uniquely defined.

    For example, [0,2,3,1] is also a valid gray code sequence according to the above definition.

    For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that.


(1)思路:该问题给我们一个数字n,要求生成n位的格雷码。考虑到格雷码相邻两个二进制数只能在一位上有差异,所以我们可以用一种从最低为开始,逐位加一的方法去解决这个问题。

我们以n=3为例。我们可以令一开始的数为000,然后在最低位加一,得到:

000 
001

然后我们在上述已知的格雷码中,从下往上在次低位加一:

000 
001 
011 
010

这里要注意加一的顺序,必须要从下往上加,因为新增加的数字如果是从上往下产生的,那么就相当于是同时在多个位上发生改变,而从下往上加可以确保只有一位发生了改变,又因为原先有的相邻格雷码之间只有一位有区别,如果在同一个位置上都加一,相邻两个之间的差异仍然只有一,因此性质还是成立的。 最后我们在最高位上加一,注意还是要从下往上:

000 
001 
011 
010 
110 
111 
101 
100

(2)代码:

#include <iostream>

#include <stdlib.h>

#include <string>

#include <vector>

using namespace std;

class Solution {
public:
    vector<int> grayCode(int n) {
        vector<int> res(1, 0);
        for (int i = 0; i < n; ++i) {
            int size = res.size();
            while (size--) {
                int curNum = res[size];
                curNum += (1 << i);
                res.push_back(curNum);
            }
        }
        return res;
    }
};

int main(){
    int n;
    cout<<"请输入位数n:";
    cin>>n;
    Solution solution;
    vector<int> result=solution.grayCode(n) ;
    for(int i=0;i<result.size();i++){
        cout<<result[i]<<"  ";
    }
    cout<<endl;
}

No.2

题目链接:Insertion Sort List

  • 题目描述:

    Sort a linked list using insertion sort.


(1)思路:该问题比较简单,要求我们用插入排序的方法实现链表的排序。插入排序即遍历链表,然后将其插入到适当的为值即可,我们可以将链表分为两部分,前半部分为已经排序好的,后半部分是还未排序的,用指针指向未排序的头结点,然后遍历排序号的部分,找到第一个大于该值的节点,然后将其插入到该节点之前一个位置即可。然后未排序部分的头结点向后移一个节点即可,直至遍历完整个链表。

(2)代码:

#include<iostream>

#include<stdlib.h>

#include<string>

using namespace std;


struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
    ListNode* insertionSortList(ListNode* head) {
        ListNode *newhead = new ListNode(-1);
        while(head != NULL){
            ListNode *temp = head->next;
            ListNode *cur = newhead;
            while(cur->next != NULL &&cur->next->val < head->val){
                cur = cur->next;
            }
            head->next = cur->next;
            cur->next = head;
            head = temp;
        }
        return newhead->next;
    }
};

int main(){
     cout<<"请输入链表长度 N :";
     int n;
     cin>>n;
     ListNode *head = NULL;
     ListNode *p;
     int a;
     cout<<"请输入链表元素:"; 
     while(n--){
        cin>>a;
        if(head == NULL){
            head = (ListNode *)malloc(sizeof(ListNode));
            head->val = a;
            p = head;
        }
        else{
            p->next = (ListNode *)malloc(sizeof(ListNode));
            p = p->next;
            p->val = a;
        }
     } 
     p->next = NULL;
     Solution solution;
     ListNode* result = solution.insertionSortList(head);
     while(result != NULL){
        if(result->next == NULL){
            cout<<result->val<<endl;
        }
        else{
             cout<<result->val<<" -> ";
        }  
        result = result->next;
     }


    cout<<endl;
     return 0;
}

No.3

题目链接:Word Break

  • 题目描述:

    Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words. You may assume the dictionary does not contain duplicate words. For example, given

    s = “leetcode”, dict = [“leet”, “code”].

    Return true because “leetcode” can be segmented as “leet code”.


(1)思路:该问题给了我们一个字符串s和一个字典dict,要求我们根据字典判断字符串s能否全部根据字典中的单词进行分割。我们可以这样思考:字符串s可以被全部分割,即组成字符串s的子字符串全部都在字典dict中,而判断子字符串是否在dict中,我们可以一个一个字符的判断,用一个bool类型的数组或者向量,向量或数组的长度为字符串s的长度加1,然后每一位初始设为false,第一位设为true。然后遍历没一个字符,如果该字符在dict中就将对应位置的数组设为true,每一位的判断先要满足前一位为true的条件,然后再进行判断,最后得出的字符串s长度的位置为真即代表可以完全分割。

(2)代码:

#include<iostream>

#include<stdlib.h>

#include<stdio.h> 

#include<string>

#include<vector>

#include<algorithm>

using namespace std;

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        int size = s.size();
        vector<bool> dp(size + 1, false);
        dp[0] = true;
        for(int i = 1; i <= size; i++){
            for(int j = 0; j < i; j++){
                if(dp[j]){
                    vector<string>::iterator re = find( wordDict.begin(), wordDict.end(),  s.substr(j, i - j)); 
                    if (re != wordDict.end()) 
                        dp[i] = true;
                }
            }
        }
        return dp[size];
    }
};

int main(){
    string s;
    cout<<"请输入原始字符串s:";
    cin>>s;
    cout<<"请输入字典向量的额元素个数n:";
    vector<string> wordDict;
    int n;
    string a;
    cin>>n;
    while(n--){
        cin>>a;
        wordDict.push_back(a);
    }
    Solution solution;
    bool result=solution.wordBreak(s, wordDict);
    if(result == true) cout<<"True"<<endl;
    else cout<<"False"<<endl;
    return 0;
} 

No.4

题目链接:Combination Sum III

  • 题目描述:

    Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.

    Example 1:

    Input: k = 3, n = 7

    Output:

    [[1,2,4]]

    Example 2:

    Input: k = 3, n = 9

    Output:

    [[1,2,6], [1,3,5], [2,3,4]]


(1)思路:该问题给出我们两个参数,k和n,要求我们列出k个数和为n的所有组合,可以用的数字为1~9。我们可以采用递归循环调用的方法:我们可以用一个向量num存现有的数字的集合,n是k个数字之和,如果n小于0,则直接返回;如果n正好等于0,而且此num中数字的个数正好为k,说明此时是一个正确解,将其存入结果result中。

(2)代码:

#include<iostream>

#include<vector>

#include<string>

#include<algorithm>

using namespace std; 

class Solution {
public:
    vector<vector<int> > combinationSum3(int k, int n) {
        vector<vector<int> > result;
        vector<int> num;
        help(k, n, 1, num, result);
        return result;
    }
    void help(int k, int n, int level, vector<int> &num, vector<vector<int> > &result){
        if(n < 0) return;
        if(n == 0 && num.size() == k) result.push_back(num);
        for(int i=level;i<=9;++i){
            num.push_back(i);
            help(k, n-i, i+1, num, result);
            num.pop_back();
        }
    }
};

int main(){
    int k, n;
    cout<<"请输入 k 和 n :";
    cin>>k>>n;
    Solution solution;
    vector<vector<int> > result = solution.combinationSum3(k, n);
    int size = result.size();
    for(int i=0;i<size;i++){
        int size1=result[i].size();
        cout<<"[";
        int j;
        for(j=0;j<size1-1;j++){
            cout<<result[i][j]<<", ";
        }
        cout<<result[i][j]<<"]"<<endl;
    } 
    return 0;
}