【26-30】剑指offer

来源:互联网 发布:漫画配音软件 编辑:程序博客网 时间:2024/06/06 02:20

26.题目描述

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

注意:采用递归实现。注意指向指针的指针的使用。

#include <iostream>

using namespace std;

 

struct TreeNode {

       intval;

       structTreeNode *left;

       structTreeNode *right;

       TreeNode(intx) :

                     val(x),left(NULL), right(NULL) {

       }

};

 

TreeNode* pre;

 

class Solution {

public:

   TreeNode* Convert(TreeNode* pRootOfTree)

    {

              //调用遍历函数实现,二叉树序列换

              TreeNode*pInitNodeLast = NULL;

              ConvertNode(pRootOfTree,&pInitNodeLast);

      

              //找出最左变的结点

              TreeNode* pListHead = pInitNodeLast;

              while(pRootOfTree!= NULL && pListHead->left != NULL)

              {

                     pListHead= pListHead->left;

              }

 

              //返回链表头

              returnpListHead;

    }

      

       voidConvertNode(TreeNode *root, TreeNode** pInitNodeLast)

       {

              //如果结点为NULL,则返回

              if(root== NULL)

                     return;

              //如果结点的左子节点不为NULL,则递归左子树

              if(root->left!= NULL)

                     ConvertNode(root->left,pInitNodeLast);

 

              //操作

              TreeNode* pCurrent = root;

              pCurrent->left= *pInitNodeLast;

              if((*pInitNodeLast)!= NULL)

                     (*pInitNodeLast)->right= pCurrent;

              (*pInitNodeLast)= pCurrent;

 

              //如果右子节点不为NULL,则遍历右子树

              if(root->right!= NULL)

                     ConvertNode(root->right,pInitNodeLast);

       }

 

       //创建二叉树

       TreeNode* CreateTree()

       {

              intval = 0;

              cout<<"Pleaseinput val(-1):";

              cin>>val;

              if(val== -1)

                     returnNULL;

              TreeNode*root = new TreeNode(val);

              root->left=CreateTree();

              root->right=CreateTree();

              returnroot;

       }

       //前序打印二叉树

       voidPrePrintTree(TreeNode *root)

       {

              if(root== NULL)

                     return;

              cout<<root->val<<"";

              PrePrintTree(root->left);

              PrePrintTree(root->right);

       }

};

 

int main()

{

       Solutions;

       TreeNode*root = s.CreateTree();

       s.PrePrintTree(root);

       cout<<endl;

       TreeNode*ListHead = s.Convert(root);

       TreeNode*temp = ListHead;

       while(temp!= NULL)

       {

              cout<<temp->val<<"";

              temp= temp->right;     

       }

       return0;

}

 

27.题目描述

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cabcba结果请按字母顺序输出。

输入描述:

输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

思路:采用递归实现。1.从字符串中选择第一个字符,分别与后面的字符进行替换,若满足到达字符串末尾,则保存该字符串;2.递归;3.将替换的字符还原。若有重复则继续循环。具体见代码:

 

#include<iostream>

#include<vector>

#include<string>

using namespace std;

 

class Solution {

public:

       voidPermutation(char *pStr, char *pBegin,vector<string> &perm)

       {

              if(*pBegin== '\0')

              {

                     //cout<<pStr<<endl;

                     perm.push_back((string)pStr);

              }

              //将前面的字符与后面的字符一次交换

              for(char*pCh = pBegin; *pCh != '\0'; pCh++)

              {

                     if(pCh!= pBegin && *pCh == *pBegin)

                            continue;

                    

              //     char tempChar = *pBegin;

              //     *pBegin = *pCh;

              //     *pCh = tempChar;

 

                     chartempChar = *pCh;

                     char*p = pCh;

                     while(p!= pBegin)

                     {

                            *p= *(p-1);

                            p--;

                     }

                     *pBegin= tempChar;

 

                     Permutation(pStr,pBegin+1, perm);

 

              //     tempChar = *pBegin;

              //     *pBegin = *pCh;

              //     *pCh = tempChar;

 

                     tempChar= *pBegin;

                     p= pBegin;

                     while(p!= pCh)

                     {

                            *p= *(p+1);

                            p++;

                     }

                     *p= tempChar;

              }

       }

 

   vector<string> Permutation(string str)

       {

              //如果输入的字符串为NULL,则返回

              if(str.empty())

                     returnvector<string>(0);

 

              //如果输入字符串不为NULL,则递归获取排列组合

              vector<string>perm;

              Permutation(const_cast<char*>(str.c_str()),const_cast<char *>(str.c_str()), perm);

 

              returnperm;

    }

};

 

int main()

{

       stringstr1 = "123";

       Solutions;

       vector<string>perm = s.Permutation(str1);

       cout<<endl;

       vector<string>::iteratorite = perm.begin();

       for(;ite != perm.end(); ite++)

              cout<<*ite<<endl;

 

      return 0;

}

 

28.题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0

   思路:采用快速排序算法。由于数字出现的次数超过了数组的一半,所以当取数轴小于数组的一半,则在右侧只进行右侧排序,否则在左侧进行排序。

#include <iostream>

#include <vector>

using namespace std;

 

bool g_bInputInvalid = false;

class Solution {

public:

   int MoreThanHalfNum_Solution(vector<int> numbers)

       {

              //检查numbers是否满足合法

              if(ChenkInvalidArray(numbers))

                     return0;

 

              returnQuickSortMoreThanHalfNum(numbers, 0, numbers.size()-1);

    }

      

       intQuickSortMoreThanHalfNum(vector<int> &numbers, int start, int end)

       {

              //获取取数轴的值

              intpivot;

              intmid = (end - start + 1)>>1;

              pivot = Partition(numbers, start, end);

              while(pivot!= mid)

              {

                     if(pivot< mid)

                     {

                            start= pivot + 1;

                            pivot= Partition(numbers, start, end);

                     }

                     else

                     {

                            end= pivot - 1;

                            pivot= Partition(numbers, start, end);

                     }

              }

 

              intresult = numbers[mid];

              if(!CheckMoreThanHalf(numbers,result))

                     return0;

              returnresult;

       }

 

       intPartition(vector<int> &numbers, int start, int end)

       {

              intpivotkey;

              inttemp = pivotkey = numbers[start];

              while(start< end)

              {

                     while(start< end && numbers[end] >= pivotkey)

                            end--;

                     numbers[start]= numbers[end];

                     while(start< end && numbers[start] <= pivotkey)

                            start++;

                     numbers[end]= numbers[start];

              }

              numbers[start]= temp;

              returnstart;

       }

 

       boolChenkInvalidArray(vector<int> numbers)

       {

              g_bInputInvalid= false;

              if(numbers.size()== 0)

                     g_bInputInvalid= true;

              returng_bInputInvalid;

       }

      

       boolCheckMoreThanHalf(vector<int> numbers, int result)

       {

              inttimes = 0;

              vector<int>::iteratorite = numbers.begin();

              for(; ite!=numbers.end();ite++)

              {

                     if(*ite== result)

                            times++;

              }

              boolisMoreThanHalf = true;

              if(times*2<= numbers.size())

              {

                     isMoreThanHalf= false;

                     g_bInputInvalid=true;

              }

              returnisMoreThanHalf;

       }

};

 

int main()

{

       freopen("data.txt","r",stdin);

       vector<int>numbers(9);

       vector<int>::iteratorite = numbers.begin();

       for(; ite != numbers.end(); ite++)

              cin>>*ite;

 

       Solutions;

       cout<<"Thenum is:"<<s.MoreThanHalfNum_Solution(numbers)<<endl;

 

       return0;

}

 

29.题目描述

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,88个数字,则最小的4个数字是1,2,3,4,

 

思路:按照上一题的思路进行。注意处理边界。也可以采用红黑树来实现。

#include <iostream>

#include <vector>

using namespace std;

 

class Solution {

public:

   vector<int> GetLeastNumbers_Solution(vector<int> input, intk)

       {

              //检查numbers是否满足合法

              vector<int>result(k);

              QuickSortMoreThanHalfNum(input,k, result);

              returnresult;

    }

      

       voidQuickSortMoreThanHalfNum(vector<int> &numbers, int k,vector<int> &result)

       {

              if(numbers.size()== 0 || k > numbers.size() || k <= 0)

              {

                     result.resize(0);

                     return;

              }

 

              //获取取数轴的值

              intstart = 0;

              intend = numbers.size()-1;

              intpivot = Partition(numbers, start, end);

              while(pivot!= k-1)

              {

                     if(pivot> k-1)

                     {

                            end= pivot - 1;

                            pivot= Partition(numbers, start, end);

                     }

                     else

                     {

                            start= pivot + 1;

                            pivot= Partition(numbers, start, end);

                     }

              }

 

              for(inti= 0; i < k; i++)

              {

                     cout<<numbers[i]<<endl;

                     result[i]= numbers[i];

              }

       }

 

       intPartition(vector<int> &numbers, int start, int end)

       {

              intpivotkey;

              inttemp = pivotkey = numbers[start];

              while(start< end)

              {

                     while(start< end && numbers[end] >= pivotkey)

                            end--;

                     numbers[start]= numbers[end];

                     while(start< end && numbers[start] <= pivotkey)

                            start++;

                     numbers[end]= numbers[start];

              }

              numbers[start]= temp;

              returnstart;

       }

};

 

int main()

{

       freopen("data.txt","r",stdin);

       vector<int>numbers(13);

       vector<int>::iteratorite = numbers.begin();

       for(; ite != numbers.end(); ite++)

              cin>>*ite;

 

       Solutions;

       vector<int>temp = s.GetLeastNumbers_Solution(numbers, 6);

       ite= temp.begin();

       for(;ite != temp.end(); ite++)

              cout<<*ite<<"";

       return0;

}

 

30.题目描述

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?

注意:求取连续数组的最大和,只需要俩个参数,一个记录数组的当前求和值,另一个记录数组求和的最大值。当当前求和值小于或者等于0时更新当前求和值为当前数组对应的元素值,否则进行累加。当当前求和值大于记录数组求和的最大值,则更新记录数组求和的最大值。

#include<iostream>

#include<vector>

using namespace std;

 

bool g_IvalidInput = false;

class Solution {

public:

   int FindGreatestSumOfSubArray(vector<int> array) {

              //如果数组为NULL,则返回0

              if(array.size()== 0)

              {

                     g_IvalidInput= true;

                     return0;

              }

 

              //如果数组不为NUL,则求取连续子数组的最大和

              intnSum = 0;

              intnSumOfSubarray = 0x80000000;

              cout<<nSumOfSubarray<<endl;

              vector<int>::iteratorite = array.begin();

              for(;ite != array.end(); ite++)

              {

                     //如果和小于等于0时,则舍弃之前的求和

                     if(nSum<= 0)

                            nSum= *ite;

                     else

                            nSum+= *ite;

 

                     if(nSum> nSumOfSubarray)

                            nSumOfSubarray= nSum;

              }

              returnnSumOfSubarray;   

    }

};

 

int main()

{

       vector<int>array(8);

       freopen("data.txt","r", stdin);

       vector<int>::iteratorite = array.begin();

       for(;ite != array.end(); ite++)

       {

              cin>>*ite;

       }

       Solutions;

       cout<<s.FindGreatestSumOfSubArray(array)<<endl;

 

       return0;

}
0 0