每日六题-剑指offer(五)

剑指offer之每日六题

1.复杂链表的复制
2.二叉树与双向链表
3.字符串的排列
4.数组中出现次数超过一半的数字
5.最小的第k个数
6.连续子数组的最大和

1.复杂链表的复制

/**
先留着
**/
/*
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if (!pHead) return NULL;
    nodeClone(pHead);
    connectRandom(pHead);
    return reconnect(pHead);
    }


//[1]复制结点,插入到原结点后方
void nodeClone(RandomListNode *head)
{
    RandomListNode *pNode = head;
    while (pNode != NULL)
    {
        RandomListNode *pClone = new RandomListNode(pNode->label);
        pClone->next = pNode->next;
        pNode->next = pClone;
        pNode = pClone->next;
    }
}

//[2]还原新结点的random指针
void connectRandom(RandomListNode *head)
{
    RandomListNode *pNode = head;

    while (pNode != NULL)
    {
        RandomListNode *pClone = pNode->next;
        if (pNode->random)
        {
            pClone->random = pNode->random->next;
        }
        pNode = pClone->next;
    }
}

//[3]拆分
RandomListNode *reconnect(RandomListNode *head)
{
    RandomListNode *pNode = head;
    RandomListNode *result = head->next;
    while (pNode != NULL)
    {
        RandomListNode *pClone = pNode->next;
        pNode->next = pClone->next;
        pNode = pNode->next;
        if (pNode != NULL)
            pClone->next = pNode->next;

    }
    return result;
}

};

2.二叉树与双向链表

/**
二叉搜索树的中序遍历是从大到小的,然后记录当前节点和上一个节点pre,更新每个节点的指向,使其变成一个双向链表,递归和非递归都在这了
**/
class Solution {
public:
    TreeNode* pre=nullptr;
    TreeNode* p=nullptr;
    void ConvertSub(TreeNode* root){
        if(root==nullptr) return ;
        ConvertSub(root->left);
        if(!pre){
            pre=root;
            p=root;
        }
        else{
            pre->right=root;
            root->left=pre;
            pre=root;
        }
        ConvertSub(root->right);
    }
    TreeNode* Convert(TreeNode* root)
    {
        ConvertSub(root);
        return p;
        /*if(root==nullptr) return NULL;
        stack<TreeNode*> s;
        TreeNode* p=root;
        TreeNode* pre=NULL;
        while(p!=nullptr||!s.empty()){
            while(p!=nullptr){
                s.push(p);
                p=p->left;
            }
            p=s.top();
            s.pop();
            if(!pre){
                root=p;
                pre=root;
            }
            else{
                pre->right=p;
                p->left=pre;
                pre=p;
            }
            p=p->right;
        }
        return root;
        */
    }
};

3.字符串的排列组合

/**
我用的是传说中的交换法,将当前指针指向的值和后面的交换,递归回溯,然后用set去重排序,最后把结果保存起来
**/
class Solution {
public:
    set<string> res;
    void get_ans(string str,int begin){
        if(begin==str.length()-1)
            res.insert(str);
        else{
            for(int i=begin;i<str.length();i++){
                swap(str[begin],str[i]);
                get_ans(str,begin+1);
                swap(str[begin],str[i]);
            }
        }
    }
    vector<string> Permutation(string str) {
        vector<string> ans;
        if(str.length()==0) return ans;
        get_ans(str,0);
        set<string>::iterator p;
        for(p=res.begin();p!=res.end();p++){
            ans.push_back(*p);
        }
        return ans;
    }
};

4.数组中次数超过一半的数字

/**
map的基本用法
**/
class Solution {
public:
    map<int,int> m;
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        for(int i=0;i<numbers.size();i++){
            if(++m[numbers[i]]>(numbers.size()/2)) return numbers[i];
        }
        return 0;
    }
};

5.最小的k个数

/**
排序,保存
**/
class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        vector<int> res;
        if(input.empty()||k>input.size()) return res;
        sort(input.begin(),input.end());
        for(int i=0;i<k;i++)
            res.push_back(input[i]);
        return res;

    }
};

6.连续子树组的最大和

/**
(盗版过来的,侵删)
使用动态规划
F(i):以array[i]为末尾元素的子数组的和的最大值,子数组的元素的相对位置不变
F(i)=max(F(i-1)+array[i] , array[i])
res:所有子数组的和的最大值
res=max(res,F(i))
如数组[6, -3, -2, 7, -15, 1, 2, 2]
初始状态:
    F(0)=6
    res=6
i=1:
    F(1)=max(F(0)-3,-3)=max(6-3,3)=3
    res=max(F(1),res)=max(3,6)=6
i=2:
    F(2)=max(F(1)-2,-2)=max(3-2,-2)=1
    res=max(F(2),res)=max(1,6)=6
i=3:
    F(3)=max(F(2)+7,7)=max(1+7,7)=8
    res=max(F(2),res)=max(8,6)=8
i=4:
    F(4)=max(F(3)-15,-15)=max(8-15,-15)=-7
    res=max(F(4),res)=max(-7,8)=8
以此类推
最终res的值为8 
**/
class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        int res = array[0];
        int maxn= array[0];
        for (int i = 1; i < array.size(); i++) {
            maxn=max(maxn+array[i], array[i]);
            res=max(maxn, res);
        }
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/hengtian_real/article/details/79796946