您的位置:首页 > Web前端

每日六题-剑指offer(五)

2018-04-02 23:27 190 查看

剑指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())
4000
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;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  剑指offer