剑指offer习题集2
1.把数组排成最小的数
class Solution {
public: static bool compare(const string& s1, const string& s2) {
string t1 = s1 + s2;
string t2 = s2 + s1;
return t1 <= t2? true : false;
} string PrintMinNumber(vector<int> numbers) { string str;
int i, len = numbers.size();
if (len<) return str; string res;
vector<string> vt;
for (i = ;i<len;++i) {
stringstream stream;
stream << numbers[i];
stream >> str;
vt.push_back(str);
} sort(vt.begin(), vt.end(), compare);
for (i = ;i<len;++i)
res += vt[i];
return res;
}
};
这里使用string会比使用char*更加快捷方便。
另外使用sort而不是qsort,主要是sort是qsort的升级,且参数更少,不需要制定每个参数占据的内存空间大小。
2.字符流中第一个不重复的字符
少有的一遍通过的程序,眼泪都快流下来了
class Solution
{
public: Solution():index(){ //初始化位置
for(int i=;i<;++i)
pos[i]=-;
} //Insert one char from stringstream
void Insert(char ch)
{
if(pos[ch]==-)
pos[ch]=index;
else if(pos[ch]>=)
pos[ch]=-; ++index;
} //return the first appearence once char in current stringstream
char FirstAppearingOnce()
{
char res='#';
int minv=1e8,i; //设置字符串max值
for(i=;i<;++i){
if(pos[i]>=&&pos[i]<minv){ //若是当前位置小于min,则对min进行更新
res=(char)i;
minv=pos[i];
}
} return res;
} private:
int index;
int pos[];
};
3.求滑动窗口最大值
还是不能一遍通过,而且思维定式,真的很难找到错误的
class Solution {
public:
vector<int> maxInWindows(const vector<int>& num, unsigned int size)
{
int i,j,k,len=num.size();
vector<int> result;
if(len<size||size==)
return result; int max=num[];
for(i=;i<size;++i){ //先寻找第一个窗口的最大值
if(max<num[i])
max=num[i];
}
result.push_back(max); for(i=;i<=(len-size);++i){
j=i+size-;
if(num[j]<max){
//判断最大值是否移出滑动窗口
if(num[i-]!=max)
result.push_back(max);
else{ //确定最大值被移出滑动窗口,重新确定最大值
max=num[i];
for(k=i;k<=j;++k){
if(num[k]>max)
max=num[k];
}
result.push_back(max);
}
}else{
result.push_back(num[j]);
max=num[j];
}
}
return result;
}
};
4.表示数值的字符串(最耗人心力的程序,没有之一)
有空多做几遍,绝对练耐心
class Solution {
public: bool isdigit(const char& ch){
if(ch<=''&&ch>='')
return true;
else return false;
} void scandigits(char** str){
while(**str!='\0'&&isdigit(**str))
++(*str);
} bool isexpand(char** str){
if(**str!='E'&&**str!='e')
return false; ++(*str);
if(**str=='+'||**str=='-')
++(*str); if(**str=='\0')
return false; scandigits(str);
return (**str=='\0')?true:false;
} bool isNumeric(char* strt)
{
if(NULL==strt)
return false; bool digit=true;
char *str=strt; //排除符号干扰,找到第一个数字
while(str){
if(*str=='+'||*str=='-'){
++str;break;
}else if(isdigit(*str)){
break; //找到第一个数字
}
}
if(*str=='\0') return false; scandigits(&str);
if(*str!='\0'){
//针对小数进行处理
if(*str=='.'){
++str;
scandigits(&str); if(*str=='e'||*str=='E')
digit=isexpand(&str);
}else if(*str=='E'||*str=='e'){
digit=isexpand(&str);
}else{
digit=false;
}
} return digit&&(*str=='\0');
} };
5.字符串的排列
《剑指offer》上针对的是无重复字符串的全排列递归做法。
下面贴的是对重复字符进行处理了的全排列递归做法,为了通过测试集,对字符串进行了排序。
class Solution {
public: vector<string> Permutation(string str) { vector<string> res;
int len=str.length();
if(==len) return res;
else if(==len){
res.push_back(str); return res;
} int left=,right=len-;
Permutation(str,left,right,res);
sort(res.begin(),res.end());
return res;
} //递归实现字符交换
void Permutation(string& str,int left,int right,vector<string>& res){ if(left==right){
res.push_back(str);
}else{
for(int i=left;i<=right;++i){
if(isswap(str,left,i)){
swap(str[i],str[left]);
Permutation(str,left+,right,res);
swap(str[i],str[left]);
}
}
}
} private:
void swap(char& a,char& b){
char t=a;a=b;b=t;
} bool isswap(const string& str,const int& left,const int& right){
for(int i=left;i<right;++i)
if(str[i]==str[right])
return false;
return true;
}
};
后续会添加相应的非递归做法。
另外,此题可以扩展为多个子问题,待后续一一解决。
6.求旋转数组的最小数
没有通过测试集,不过自行调试,觉得程序应该是正确的啊
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) { int len = rotateArray.size();
if ( == len) return ;
else if ( == len) return rotateArray[]; int left = , right = len - , mid;
while (rotateArray[left] >= rotateArray[right]) { if (right - left == ) {
mid = right;break;
} mid = left + (right - left) / ; //如果下标为left/right/mid指向的三个数字相等
if (rotateArray[left] == rotateArray[right] &&
rotateArray[left] == rotateArray[mid]) {
//顺序查找最小元素
return mininorder(rotateArray, left, right);
} if (rotateArray[mid] >= rotateArray[left]) {
left = mid;
}
else if (rotateArray[mid] <= rotateArray[right]) {
right = mid;
}
} return rotateArray[mid];
} private:
int mininorder(const vector<int>& rotateArray, const int& left, const int& right) {
int min = rotateArray[left];
for (int i = left + ;i <= right;++i) {
if (rotateArray[i]<min)
min = rotateArray[i];
}
return min;
}
};
7.扑克牌顺子
class Solution {
public:
bool IsContinuous( vector<int> numbers ) { int len=numbers.size();
if(len<=) return false; //进行排序
sort(numbers.begin(),numbers.end()); int i=,zeronum=,gap,numgap=;
for(i=;i<len;i++){
if(numbers[i]==)
++zeronum;
else break;
} //从非零的下一个位置开始进行计算
for(i=i+;i<len;++i){
gap=numbers[i]-numbers[i-];
if(==gap)
return false;
else if(==gap)
continue;
else{
numgap+=gap-;
}
} if(numgap<=zeronum)
return true;
else return false;
}
};
8.丑数
此题真的不太好理解,需要重复练习几遍方能理解贯通。
class Solution {
public:
int GetUglyNumber_Solution(int index) { if(==index) return ;
else if(==index) return ; long long *uglynum=new long long[index];
uglynum[]=;
int nextuglyindex=; long long min,*p1=uglynum,*p2=uglynum,*p3=uglynum;
while(nextuglyindex<index){
min=minnum(*p1*,*p2*,*p3*);
uglynum[nextuglyindex]=min; while(*p1*<=uglynum[nextuglyindex])
++p1;
while(*p2*<=uglynum[nextuglyindex])
++p2;
while(*p3*<=uglynum[nextuglyindex])
++p3; ++nextuglyindex;
} int res= (int)uglynum[nextuglyindex-];
delete[] uglynum;
return res;
} private:
long long minnum(const long long& num1,const long long& num2,const long long& num3){
long long min=(num1<num2)?num1:num2;
return (num3<min)?num3:min;
}
};
9.正则表达式匹配
class Solution {
public:
bool match(char* str, char* pattern)
{
if(NULL==str||pattern==NULL)
return false;
else return matchstr(str,pattern);
} private:
bool matchstr(char* str,char* pattern){ if(*str=='\0'&&*pattern=='\0')
return true; if(*str!='\0'&&*pattern=='\0')
return false; if(*(pattern+)=='*'){
if(*pattern==*str||(*pattern=='.'&&*str!='\0'))
return matchstr(str+,pattern+)
|| matchstr(str+,pattern)
|| matchstr(str,pattern+);
else return matchstr(str,pattern+);
} if(*str==*pattern||(*pattern=='.'&&*str!='\0'))
return matchstr(str+,pattern+); return false;
}
};
return使用||返回几个可能结果,状态之间的变化,简直不能再赞了
10.树的子结构
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
bool HasSubtree(TreeNode* root1, TreeNode* root2)
{
bool res=false; if(root1!=NULL&&root2!=NULL){
if(root1->val==root2->val){
res=judgetree(root1,root2);
}
if(!res)
res=HasSubtree(root1->left,root2);
if(!res)
res=HasSubtree(root1->right,root2);
} return res;
} private:
bool judgetree(TreeNode* root1, TreeNode* root2){
if(root2==NULL)
return true; if(root1==NULL)
return false; if(root1->val!=root2->val)
return false; return judgetree(root1->left,root2->left)&&
judgetree(root1->right,root2->right);
}
};
以后看看能不能改进,避免递归调用。
11.栈的压入弹出
class Solution {
public:
bool IsPopOrder(vector<int> push, vector<int> pop) { bool res = false;
int len = push.size();
if (len != pop.size() || len <= ) return res; stack<int> sdata;
vector<int>::iterator nextpush = push.begin(), nextpop = pop.begin(); while (nextpop - pop.begin() < len)
{
while (sdata.empty() || sdata.top() != *nextpop)
{
if (nextpush - push.begin() == len)
break; sdata.push(*nextpush); ++nextpush;
} if (sdata.top() != *nextpop)
break; sdata.pop();
nextpop++;
} if (sdata.empty() && nextpop - pop.begin() == len)
res = true; return res;
}
};
12.二叉搜索树的后序遍历序列
class Solution {
public:
bool VerifySquenceOfBST(vector<int> sdata) { int len = sdata.size();
if (len <= ) return false; return judgeBST(sdata, , len - );
} private:
bool judgeBST(vector<int>& sdata, int left, int right) { if (right - left < ) return false; int i, j, root = sdata[right]; for (i = left;i < right;++i) {
if (sdata[i] > root)
break;
} for (j = i;j < right;++j) {
if (sdata[j] < root)
return false;
} bool leftsign = true, rightsign = true;
if (i > left) //表示有左子树
leftsign = judgeBST(sdata, left, i - ); if (i < right) //表示有右子树
rightsign = judgeBST(sdata, i, right - ); return (leftsign&&rightsign);
}
};
13.按之字形顺序打印二叉树
class Solution {
public:
vector<vector<int>> Print(TreeNode* root)
{
vector<vector<int>> res;
if (NULL == root)
return res; int i, left, right, nextlevel = , tobepush = ;
vector<int> vtmp;
std::queue<TreeNode*> nodes;
nodes.push(root); while (!nodes.empty())
{
TreeNode *nodetmp = nodes.front();
vtmp.push_back(nodetmp->val); if (nodetmp->left)
{
++nextlevel;
nodes.push(nodetmp->left);
} if (nodetmp->right)
{
++nextlevel;
nodes.push(nodetmp->right);
} nodes.pop();
--tobepush;
if ( == tobepush)
{
res.push_back(vtmp);
vtmp.clear();
tobepush = nextlevel;
nextlevel = ;
}
} for (i = ; i < res.size(); i += )
{
left = ;right = res[i].size() - ;
while (left < right)
{
swap(res[i][left], res[i][right]);
++left;--right;
}
}
return res;
} private:
void swap(int& a, int& b)
{
int tmp = a;a = b;b = tmp;
}
};
14.判断二叉树是否对称
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
if (NULL == pRoot)
return true;
else return judgeSymmetrical(pRoot->left, pRoot->right);
} private:
bool judgeSymmetrical(TreeNode* left, TreeNode* right)
{
if (NULL == left&&NULL == right)
return true; if (NULL == left || NULL == right)
return false; if (left->val != right->val)
return false; //注意此处不能判断相等返回true,因为下面还要进行判断 return judgeSymmetrical(left->left, right->right)
&& judgeSymmetrical(left->right, right->left);
}
};
很完美的思路,通过前序序列进行判断。
15.二叉树的序列化和反序列化
class Solution {
public:
char* Serialize(TreeNode *root)
{
string str;
Serialize(root, str); int i,len = str.length();
char *res = new char[len + ];
for (i = ; i < len; i++)
res[i] = str[i];
res[i] = '\0';
return res;
} TreeNode* Deserialize(char *str)
{
if (NULL == str || *str == '\0')
return NULL; int left = ; string numstr(str); TreeNode* head = Deserialize(numstr, left);
return head;
} private: void Serialize(TreeNode *root, string& str)
{
if (NULL == root)
{
str += "#,"; return;
}
else
{
ostringstream ost;
ost << root->val;
str += ost.str() + ',';
} Serialize(root->left, str);
Serialize(root->right, str);
} bool readstr(string& str,int& left, int& num)
{
if (str[left] == '#')
{
left += ; //退后至下一个数字
return false;
}
else
{
string tmp;
while (str[left] != ',' && str[left] != '\0')
{
tmp += str[left++];
}
++left;
num = atoi(tmp.c_str());
return true;
}
} TreeNode* Deserialize(string& numstr,int& left)
{
int num;
if (readstr(numstr, left, num))
{
TreeNode* root = new TreeNode(num); root->left = Deserialize(numstr, left);
root->right = Deserialize(numstr, left);
return root;
}
return NULL;
}
};
16.二叉搜索树的第K个节点
class Solution {
public:
TreeNode* KthNode(TreeNode* pRoot, unsigned int k)
{
if (NULL == pRoot || k == )
return NULL; return KthTreeNode(pRoot, k);
} private:
TreeNode* KthTreeNode(TreeNode* root, unsigned int& k)
{
TreeNode* target = NULL; if (root->left != NULL)
target = KthTreeNode(root->left, k); if (NULL == target)
{
if (k == )
target = root;
--k;
} if (NULL == target&&root->right != NULL)
target = KthTreeNode(root->right, k); return target;
}
};
根据中序遍历的方式实现寻找。
剑指offer习题集2的更多相关文章
- 剑指offer习题集1
1.打印二叉树 程序很简单,但是其中犯了一个小错误,死活找不到,写代码要注意啊 这里左右子树,要注意是node->left,结果写成root->left vector<int> ...
- 剑指offer习题集
1.重载赋值运算符函数:(具体见代码) //普通做法 CMyString& CMyString::operator=(const CMyString& str) { if (this ...
- 剑指Offer面试题:1.实现Singleton模式
说来惭愧,自己在毕业之前就该好好看看<剑指Offer>这本书的,但是各种原因就是没看,也因此错过了很多机会,后悔莫及.但是后悔是没用的,现在趁还有余力,把这本书好好看一遍,并通过C#通通实 ...
- 剑指Offer面试题:14.链表的倒数第k个节点
PS:这是一道出境率极高的题目,记得去年参加校园招聘时我看到了3次,但是每次写的都不完善. 一.题目:链表的倒数第k个节点 题目:输入一个链表,输出该链表中倒数第k个结点.为了符合大多数人的习惯,本题 ...
- 《剑指offer》面试题12:打印1到最大的n位数
面试题12:打印1到最大的n位数 剑指offer题目12,题目如下 输入数字n,按顺序打印出1到最大的n位十进制数,比如输入3,则打印出1,2,3一直到最大的三位数999 方法一 和面试题11< ...
- 《剑指offer》面试题11: 数值的整数次方
面试题11: 数值的整数次方 剑指offer面试题11,题目如下 实现函数double power(double base,int exponent),求base的exponent次方, 不得使用库 ...
- 剑指 Offer 题目汇总索引
剑指 Offer 总目录:(共50道大题) 1. 赋值运算符函数(或应说复制拷贝函数问题) 2. 实现 Singleton 模式 (C#) 3.二维数组中的查找 4.替换空格 ...
- 面试题目——《剑指Offer》
1.把一个字符串转换成整数——<剑指Offer>P29 2.求链表中的倒数第k个结点——<剑指Offer>P30 3.实现Singleton模式——<剑指Offer> ...
- 剑指Offer:面试题20——顺时针打印矩阵(java实现)
题目描述: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数 字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1, ...
随机推荐
- Android SurfaceView
今天介绍一下SurfaceView的用法,SurfaceView一般与SurfaceHolder结合使用,SurfaceHolder用于向与之关联的SurfaceView上绘图,调用SurfaceVi ...
- 去掉安卓中activity的标题栏
去掉所有Activity界面的标题栏 修改AndroidManifest.xml 在application 标签中添加android:theme="@android:style/Theme. ...
- jQuery 实现菜单
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- iOS求职之OC面试题
1.Objective-C的类可以多重继承么?可以采用多个协议么? 答:不可以多重继承,可以采用多个协议. 2.#import和#include的区别是什么?#import<> 跟 #im ...
- 监听调试web service的好工具TCPMon
监听调试web service的好工具TCPMonhttp://ws.apache.org/commons/tcpmon/download.cgi TCPMon Tutorial Content In ...
- VHDL:信号、端口以及和Verilog的区别
1.信号 信号是描述硬件系统的基本数据对象,它的性质类似于连接线.信号可以作为设计实 体中并行语句模块间的信息交流通道. 信号作为一种数值容器,不但可以容纳当前值,也可以保持历史值(这决定于 ...
- Kaiju: Fast and sensitive taxonomic classification for metagenomics
Kaiju: Fast and sensitive taxonomic classification for metagenomics 问题描述:However, nucleotide comp ...
- c++ 语言细节
#include <iostream>using namespace std;int main(){ cout << "\nHello World!\n&qu ...
- JavaBean基本用法示例(一)
一.首先创建一个类person,里面有四个成员:name,sex,age,info,添加四个成员所有的set和get方法. package com.kaly.bean; public class pe ...
- C++实现不能被继承的类——终结类 分类: C/C++ 2015-04-06 14:48 64人阅读 评论(0) 收藏
1. 问题 C++如何实现不能被继承的类,即终结类.Java中有final关键字修饰,C#中有sealed关键字修饰,而C++目前还没有类似的关键字来修饰类实现终结类,需编程人员手动实现. ...