#include<iostream>
#include<string>
#include<fstream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
//1.数组
//2.链表
//
class ListNode{
public:
int val;
ListNode *next;
ListNode(int x){
val = x;
next = NULL;
}
ListNode(){
next = NULL; //显式构造函数,每次对新声明的链表类进行初始化,即表示
//创建一个新的"空"链表,链表中只有头指针,并且头指针的值为NULL,表示头指针
//指向的部分也无任何数据元素
}
void Insert(ListNode *head,ListNode *node,int position);
void Output(ListNode *head);
};
void ListNode::Insert(ListNode *head,ListNode *node,int position){ //position表示要插入的位置
if(head==NULL){ //在头指针为空指针的情况下,链表是空的,无任何数据元素
//包括头结点在内.因此呢,我们在插入节点的时候,如果发现头结点为空指针
head = node; //的情况,那么这就意味着我们插入的这个节点要将其设置为头结点,
return; //而后一一插入的节点则接在该节点的后方,并且通过这个节点从头开始遍历
//能够遍历到链表中所有的数据元素
}
if(position==0){ //插入的是第0个位置,为了方便,我们暂且规定头结点为第0个节点
//那么如果插入的是第0个位置的话,说明插入的节点要成为新的头结点
//而不管之前有没有头结点
node -> next = head;
head = node; //完成头结点的更新,表示头结点现在是node节点
return;
}
ListNode *current_node = head; //从头结点开始遍历插入的位置
int i = 0; //表示已经遍历过的节点数目
while(current_node -> next != NULL && i < position-1){
//不断寻找要插入的位置的前一个位置,然后插入在这个位置的节点与下一个位置的节点之间
current_node = current_node -> next; //不断更新current_node的值
i++;
}
if(i == position-1){ //找到了插入的位置,先更新插入节点的指针域,记录当前遍历到的位置的下一个节点
//然后再接上前面的节点
node -> next = current_node -> next;
current_node -> next = node;
}
}
void ListNode::Output(ListNode *head){
if(head==NULL){
return; //链表为空链表,无任何数据元素可输出
}
ListNode *current_node = head; //从头结点开始遍历
while(current_node!=NULL){
cout << current_node -> val << " ";
current_node = current_node -> next;
}
cout << endl;
}
//
//
//
//第1.1题
bool duplicate_11(int numbers[], int length, int* duplication) {
int *copy = new int[length]();//copy一一对应
int count=0;//dup计数器
for(int i=0;i<length;i++){
if(copy[numbers[i]]==-1){
duplication[count++] = numbers[i];
cout<<duplication[0];
return true;
}
else copy[numbers[i]]=-1;
}
return false;
}
//第1.2题
int replace_12(const vector<int>& A,int pos){
vector<int> B(A);
//for (int i = 0; i < B.size(); i++) {
//cout << B.at(i) << endl;
//}
B.at(pos)=1;
int mut=1;
for(int i=0;i<A.size();i++){
mut=mut*B[i];
}
return mut;
}
vector<int> multiply_12(const vector<int>& A) {
//B是A中元素连乘,去掉i
//给一个A的引用
vector<int> B;
cout<<A.size();
int len = A.size();
for (int i =0;i<len;i++){
B.push_back(replace_12(A,i));
cout<<B.back()<<endl;
}
return B;
}
//第1.3题
//在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
bool find_13(int target, vector<vector<int> > array) {
int row=array.size();
int col=array[0].size();
//从左下角找
int i=row-1,j=0;
while(i>0&&j<col){
if(target==array[i][j]){
return true;
}
else if(target>array[i][j]){
j++;continue;
}
else{
i++;continue;
}
}
return false;
}
//第2.1题
//一个链表中包含环,请找出该链表的环的入口结点。//用例中的入口应该是2
ListNode* EntryNodeOfLoop_21(ListNode* pHead)
{
//遍历的过程中标记遇到的节点
//记录上一个
//断链法
if(pHead==NULL||pHead->next==NULL) return NULL;
ListNode *pri=pHead;
ListNode *cur=pHead->next;
//ListNode pri;
while(cur!=NULL){
cout<<pri->val;
pri->next=NULL;
pri = cur;
cur=cur->next;
}
return pri;
}
ListNode* EntryNodeOfLoop_211(ListNode* pHead){
//快指针,慢指针相遇法
//快每次走2,慢走1,相遇时候是环的长度
//然后fast从头走再次相遇时,就是入口
//第一步,找环中相汇点。分别用p1,p2指向链表头部,p1每次走一步,p2每次走二步,直到p1==p2找到在环中的相汇点。
//第二步,找环的入口。接上步,当p1==p2时,p2所经过节点数为2x,p1所经过节点数为x,设环中有n个节点,p2比p1多走一圈有2x=n+x; n=x;可以看出p1实际走了一个环的步数,再让p2指向链表头部,p1位置不变,p1,p2每次走一步直到p1==p2; 此时p1指向环的入口。
if(pHead == NULL || pHead->next == NULL)
return NULL;
ListNode *p1 = pHead;
ListNode *p2 = pHead;
while(p2 != NULL && p2->next != NULL ){
p1 = p1->next;
p2 = p2->next->next;
if(p1 == p2){
p2 = pHead;
while(p1 != p2){
p1 = p1->next;
p2 = p2->next;
}
if(p1 == p2)
return p1;
}
}
return NULL;
}
//第2.2题
//在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
ListNode* deleteDuplication(ListNode* pHead)
{
排序的...则连续分布
每次读取一个判断跟后面的值是否相同,相同就标记,直到遇到不用的,则这一段是要删除的
//if(pHead==NULL||pHead->next==NULL){
// return pHead;
//}
//if(pHead->next->next==NULL){
// if(pHead->val==pHead->next->val){
// return NULL;
// }
// else{
// return pHead;
// }
//}
//ListNode *del;//删除的起点
//ListNode *cur=pHead;//后锋军 //前探是cur->next和cur->next->next
//while(cur->next->next!=NULL){
// if(cur->next->val==cur->next->next->val){
// //如果前探和前前探相同,则下一个为删除的起点
// del=cur;//cur后面的点都不要了,相同值是del->next->val
// cur=cur->next->next;//cur移动到后面
// while(del->next->val==cur->next->val){//只要和cur->next的值相同 都是要删的
// cur=cur->next;
// }
// //直到不一样的时候,此时cur不同于del
// del->next=cur->next;//把里面的点直接释放掉//cur有可能是下一串的起点
// }
//}
处理最后两个
//按照删除的思路太繁琐,逆向思考,删除变成新建,不重复的节点重新连成一个表
if (pHead == NULL || pHead->next == NULL) { // 只有0个或1个结点,则返回
return pHead;
}
if (pHead->val == pHead->next->val) { // 当前结点是重复结点
ListNode *pNode = pHead->next;
while (pNode != NULL && pNode->val == pHead->val) {
// 跳过值与当前结点相同的全部结点,找到第一个与当前结点不同的结点
pNode = pNode->next;
}
return deleteDuplication(pNode); // 从第一个与当前结点不同的结点开始递归
} else { // 当前结点不是重复结点
pHead->next = deleteDuplication(pHead->next); // 保留当前结点,从下一个结点开始递归
return pHead;
}
}
//第2.3题
//输入一个链表,从尾到头打印链表每个节点的值。
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> result;
ListNode *i=head;
stack<int> sta;
while(i!=NULL){
sta.push(i->val);
i=i->next;
}
while(!sta.empty()){
//cout<<sta.pop();
result.push_back(sta.top());
sta.pop();
}
return result;
}
//第3.1题 700ms 太长了
//大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39 F(0)=1,F(1)=1, F(n)=F(n-1)+F(n-2)
int Fibonacci_1(int n) {
//F(0)=1,F(1)=1, F(n)=F(n-1)+F(n-2)
//递归
if(n<0) return 0;
if(n==0||n==1) return 1;
else {
return Fibonacci_1(n-1)+Fibonacci_1(n-2);
}
}
//用动态规划来做 5ms
int Fibonacci(int n) {
int f = 0, g = 1;
//每次计算只于前两个有关 减少代价
while(n>0) {
n--;
g= g+f;
f= g-f;
//首先判断有几个值,f表示当前值f(n),g表示下一个值f(n+1),则第一次循环g表示f(n+2),f-g后f表示f(n+1) 左脚踩右脚上天法。至于n只表示是第几个数,只要够减就行
}
return f;
}
//第3.2题
// 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
int jumpFloor_1(int number) {//529ms
//跳n介,有几种跳法,x=1或x=2 排列组合
//可以用递归或者动态规划来做
//递归法
//int x=0;
if(number==0) return 0;
else if(number==1) return 1;
else if(number==2) return 2;//两种跳法
else{
return jumpFloor_1(number-1)+jumpFloor_1(number-2);//拆解的时候自带了加的数字
}
}
int jumpFloor(int number) {
//跳n介,有几种跳法,x=1或x=2 排列组合
//可以用递归或者动态规划来做
//动态规划法 左脚踩右脚法
//f(0)=0;f(1)=1;
if(number<=0) return 0;
if(number==1||number==2) return number;
int f=1,g=2;//
while(number>2)//number循环的起始处要小心
{
number--;
g=g+f;//先根据f(n)和f(n+1)得到f(n+2)
f=g-f;//再根据f(n+2)和f(n)得到f(n+1) 完成一次迭代
}
return g;
}
//第3.3题
int jumpFloorII(int number) {
//变态死青蛙
//每次能跳1-n介 化简出通项f(n)=2*f(n-1)
if(number==0) return 0;
else if(number ==1) return 1;
else
return jumpFloorII(number-1)*2;
}
//第3.4题
//我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
int rectCover_1(int number) {
//递归法
//f0=0,f1=1,f2=2,f3=3...斐波那契
//fn=f(n-1)+f(n-2)//n-1表示顺着放,n-2表示占位置的放
if(number<=0) return 0;
else if(number==1||number==2) return number;
else
return rectCover_1(number-1)+rectCover_1(number-2);
}
int rectCover(int number) {
//动态规划法
//f0=0,f1=1,f2=2,f3=3...斐波那契
//fn=f(n-1)+f(n-2)//n-1表示顺着放,n-2表示占位置的放
if(number<=0) return 0;
else if(number==1||number==2) return number;
int f=1,g=2;
while (number>2){
number--;
g=g+f;
f=g-f;
}
return g;
}
//第四题
//将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
//字符'0'到'9'的ascii值的低4个二进制位刚好就是0到9所以str[i]&0xf等于str[i]-'0'。 位运算会比乘法运算效率高那么一点点点点...
int StrToInt(string str) {
//跟位置有关
//单个char转为int
//非法检测
if(str.empty())
return 0;
int symbol = 1;//默认符号为正
if(str[0] == '-'){//处理负号
symbol = -1;
str[0] = '0'; //这里是‘0’ 不是0
}else if(str[0] == '+'){//处理正号
symbol = 1;
str[0] = '0';
}
int sum = 0;
for(int i=0;i<str.size();++i){
if(str[i] < '0' || str[i] > '9'){
sum = 0;//只要有非法符号,则sum为0 最后返回值为0
break;
}
sum = sum *10 + str[i] - '0';//str[i]里面是数字的ascii码 可以直接计算的 //从低位开始 每次sum翻10倍计算
}
return symbol * sum;//最后计算符号
}
//5.1
//请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配
bool match(char* str, char* pattern)
{
//用递归的思想
}
//5.2
//请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
bool isNumeric(char* string)
{
//枚举首先考虑有哪些情况
}
//5.3
//Insert one char from stringstream
void Insert(char ch)
{
}
//return the first appearence once char in current stringstream
char FirstAppearingOnce()
{
}
int main() {
//测试用例们~~
//第1.1题
//int n[7]={1,2,3,4,4,6,7};
//int dup[7];
//duplicate_11(n,7,dup);
//第1.2题
//int n[7]={1,2,3,4,5,6,7};
//vector<int> vec(n,n+7);
//multiply_12(vec);
//第1.3题
//int mux[3][3]={{1,2,3},{2,3,4},{3,4,5}};
//for(int i =0;i<3;i++){
// for(int j=0;j<3;j++){
// cout<<mux[i][j];
// }
// cout<<endl;
//}
//vector<vector<int>> vec;
//vector<int> vec0(mux[0],mux[0]+3);
//vector<int> vec1(mux[1],mux[1]+3);
//vector<int> vec2(mux[2],mux[2]+3);
//vec.push_back(vec0);
//vec.push_back(vec1);
//vec.push_back(vec2);
//for(int i =0;i<3;i++){
// for(int j=0;j<3;j++){
// cout<<vec[i][j];
// }
// cout<<endl;
//}
//cout<<find_13(5,vec);
//第2.1题
//ListNode *a = new ListNode(1);
//ListNode *b = new ListNode(2);
//ListNode *c = new ListNode(3);
//ListNode *d = new ListNode(4);
//ListNode listhead;//没什么意义的,为了调用
//listhead.Insert(a,b,1);
//listhead.Insert(a,c,2);
//listhead.Insert(a,d,3);
//d->next = b;
listhead.Output(a);
//cout<<"aa"<<EntryNodeOfLoop_211(a)->val;
//第2.2题
//ListNode *a = new ListNode(1);
//ListNode *b = new ListNode(2);
//ListNode *c = new ListNode(3);
//ListNode *d = new ListNode(3);
//ListNode *e = new ListNode(4);
//ListNode *f = new ListNode(4);
//ListNode *g = new ListNode(5);
//ListNode listhead;//没什么意义的,为了调用
//listhead.Insert(a,b,1);
//listhead.Insert(a,c,2);
//listhead.Insert(a,d,3);
//listhead.Insert(a,e,4);
//listhead.Insert(a,f,5);
//listhead.Insert(a,g,6);
//listhead.Output(deleteDuplication(a));
//第2.3题
//ListNode *a = new ListNode(1);
//ListNode *b = new ListNode(2);
//ListNode *c = new ListNode(3);
//ListNode *d = new ListNode(4);
//ListNode listhead;//没什么意义的,为了调用
//listhead.Insert(a,b,1);
//listhead.Insert(a,c,2);
//listhead.Insert(a,d,3);
//vector<int> re = printListFromTailToHead(a);
//for(int i=0;i<re.size();i++){
// //cout<<re.size();
// cout<<re[i];
//}
//第3.1题
// cout<<Fibonacci(6);
//第3.2题
//cout<<jumpFloor(5);
//第3.3题
//cout<<jumpFloorII(3);
//第3.4题
// cout<<rectCover(3);
//第4题
//string a="123456";
//string b="12a3";
//cout<<StrToInt(a)<<endl;
//cout<<StrToInt(b)<<endl;
//5.1
//char str[3]={'a','a','a'};
//char pat[3]={'a','.','a'};
//cout<<match(str,pat);
//5.2
//5.3
cout<<endl;
system("pause");
return 0;
}`
面经准备:剑指offer 刷题 代码及笔记 C/C++ 版
最新推荐文章于 2023-03-16 14:10:36 发布