考虑是否全面:P29
将一个字符串转换为整数
- 非数字字符 2. 正负号 3.最大正整数,最小负整数以及溢出
- 空指针
P30
求链表中的倒数第K个节点
- 空指针 2. 节点总数小于K
P55
二维数组中的查找:每一行递增,每一列递增
解法:从右上角开始或者左下角
bool Find(int target, vector<vector<int> > array) {
int row = array.size();
if(row == 0 )
return false;
int col = array[0].size();
if(col==0) return false;
int i = 0, j = col-1;
while(i<row && j >=0 ){
if( array[i][j]==target) return true;
else if(array[i][j] > target){
j--;
}else{
i++;
}
}
return false;
}
第二版
P39
数组中重复的数字
方法一:用哈希表,时间复杂度是O(n), 空间复杂度是O(n)
https://www.nowcoder.com/practice/623a5ac0ea5b4e5f95552655361ae0a8?tpId=13&tqId=11203&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
bool duplicate(int numbers[], int length, int* duplication) {
map<int,int> m;
for(int i=0; i< length; i++){
if( m.count(numbers[i])!=0 ){
*duplication = numbers[i];
return true;
}else{
m[numbers[i]]=1;
}
}
return false;
}
方法二:利用数字范围在0~n-1这一点
尽管有一个两重循环,但是每个数字最多只要交换两次就能找到属于它自己的位置,因此时间复杂度O(n),空间复杂度O(1)
bool duplicate(int numbers[], int length, int* duplication) {
for(int i=0 ; i < length; i++){
while( numbers[i]!=i){
int a = numbers[numbers[i]];
if( a == numbers[i]){
*duplication = a;
return true;
}else{
numbers[numbers[i]] = numbers[i];
numbers[i] = a;
}
}
}
return false;
}
不修改数组找出重复的数字
方法一:借助辅助数组,数字是m,就将其复制到m的位置
但是这样,空间复杂度是O(n)
方法二:二分查找的思想,但是不能保证找出所有重复的数字P61,在一定取值范围内,如果个数大于范围,那么一定有重复。题干是长度为n+1的数组里所有的数字都在1~n范围内。
取值范围是1~n,个数为n+1> n,因此一定有重复。
时间复杂度是O(nlogn)
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int num = nums.size();
int start = 1, end = num-1;
int mid;
while(start<=end){
mid = (start+end)/2;
int cnt = 0;
for(int i=0;i<num;i++){
if(nums[i]<=mid && nums[i]>=start)
cnt++;
}
if(start == end){
if(cnt>1) return start;
else break;
}
if(cnt > (mid-start+1)){
end = mid;
}else{
start = mid+1;
}
}
return -1;
}
};
P54
替换空格
C/C++中每个字符串都以字符’\0’作为结尾。
注意:字符串的长度不包括\0,但是大小包括。
string Str="ABC";
printf("%d",Str.length());//结果是3
printf("%d",sizeof("ABC"));//结果是4
这道题的代码耗费了我很长时间,总是发生段错误,原来自己在str[end1]!=’ '处,忘记写str了。同时这道题目还要记得把\0拷贝过去。
从后往前替换,时间复杂度是O(n)
void replaceSpace(char *str,int length) {
if(str == NULL || length <=0 ) return ;
int cnt = 0;
int length_origin = 0;
int i=0;
while(str[i]!='\0'){
if(str[i]==' ')
cnt++;
length_origin++;
i++;
}
int new_length = length_origin + 2*cnt;
if( new_length + 1 > length) return ;
int end1 = length_origin;
int end2 = new_length;
while(end1!=end2){
if( str[end1] !=' '){
str[end2] = str[end1];
end2--;
}else{
str[end2--] = '0';
str[end2--]= '2';
str[end2--] = '%';
}
end1--;
}
}
P55
相关题目以及举一反三
https://leetcode.com/problems/merge-sorted-array/submissions/
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int index = m+n-1;
int end1 = m-1, end2 = n-1;
while(end2>=0 && end1>=0){
if(nums2[end2] >=nums1[end1]) {
nums1[index--]=nums2[end2--];
}else{
nums1[index--] = nums1[end1--];
}
}
while(end2>=0){
nums1[index--] = nums2[end2--];
}
while(end1>=0){
nums1[index--] = nums1[end1--];
}
}
};
P58
从尾到头打印链表
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> v;
ListNode * tmp = head;
while(tmp){
v.push_back(tmp->val);
tmp = tmp->next;
}
reverse(v.begin(),v.end());
return v;
}
还可以使用栈结构,递归在本质上就是一个栈结构,因此还可以用递归实现。
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> v;
ListNode * tmp = head;
if(tmp==NULL) return v;
dfs(v, tmp);
return v;
}
private :
void dfs(vector<int> & v, ListNode * node){
if(node->next == NULL)
v.push_back(node->val);
else{
dfs(v, node->next);
v.push_back(node->val);
}
}
};
树的操作会涉及大量的指针,如果面试官想考察在有复杂指针操作的情况下写代码的能力,,,,,
二叉树的遍历方式:前序遍历,中序遍历,后序遍历
每种遍历都有递归和循环两种不同的实现方法,需要对3种遍历的6种实现方法了如指掌。
二叉树的遍历还有宽度优先遍历。
二叉搜索树可以平均在O(logn)的时间内找到节点。
二叉树的另外两个特例是堆和红黑树。
堆分为最大堆,最小堆。在最大堆种根节点的值最大,有很多需要快速找到最大值或最小值的问题都可以用堆来解决。
红黑树是将节点定为红黑两种颜色,通过规则确保从根节点到叶节点的最长路径的长度不超过最短路径的两倍。在c++的STL种,set,multiset,map,multimap等数据结构都是通过红黑树实现的。
P62
重建二叉树
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
int pre_start = 0, pre_end = pre.size()-1;
int in_start = 0, in_end = vin.size()-1;
return construct(pre, vin, pre_start, pre_end, in_start, in_end);
}
private:
TreeNode * construct(vector<int> & pre, vector<int> & vin, int pre_start, int pre_end, int in_start, int in_end){
if( pre_start> pre_end || in_start>in_end) return NULL;
TreeNode * root = new TreeNode(pre[pre_start]);
int loc;
for(int i= in_start; i<= in_end; i++){
if(vin[i]==pre[pre_start]){
loc = i;
}
}
root->left = construct(pre, vin,pre_start+1, loc-in_start+pre_start, in_start,loc-1 );
root->right = construct(pre,vin, loc-in_start+pre_start+1, pre_end, loc+1, in_end);
return root;
}
};
P65
二叉树的下一个节点:中序遍历序列的下一个节点
如果节点有右子树,那么下一个节点是右子树种最左子节点
如果节点没有右子树:如果节点是父节点的左节点,那么下一个节点就是它的父节点;如果节点是父节点的右节点,需要沿着父节点一直向上遍历,直至找到一个是它父节点左节点的节点,如果这样的节点存在,那么这个节点的父节点就是要找的下一个节点。
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{ if(pNode == NULL) return NULL;
if( pNode->right!=NULL){
TreeLinkNode * tmp = pNode->right;
while(tmp->left){
tmp = tmp->left;
}
return tmp;
}else {
TreeLinkNode * t = pNode->next;
TreeLinkNode * tt = pNode; // 注意此处的更新
while(t && t->right== tt){
tt = t;
t = tt->next;
}
return t;
}
}
};
P68
通常栈是一个不考虑排序的数据结构,因此需要O(n)时间才能找到栈中最大或最小的元素。如果想在O(1)时间内得到栈的最大值或者最小值,则需要对栈做特殊的设计。
用两个栈实现队列
https://leetcode.com/problems/implement-queue-using-stacks/description/
方法一:
class Solution
{
public:
void push(int node) {
while(!stack2.empty()){
int tmp = stack2.top();
stack2.pop();
stack1.push(tmp);
}
stack1.push(node);
}
int pop() {
while(!stack1.empty()){
int tmp = stack1.top();
stack1.pop();
stack2.push(tmp);
}
int res = stack2.top();
stack2.pop();
return res;
}
private:
stack<int> stack1;
stack<int> stack2;
};
方法二:
class Solution
{
public:
void push(int node) {
stack1.push(node);
}
int pop() {
int res;
int tmp;
if( stack2.empty()){
while(!stack1.empty()){
tmp = stack1.top();
stack1.pop();
stack2.push(tmp);
}
}
res = stack2.top();
stack2.pop();
return res;
}
private:
stack<int> stack1;
stack<int> stack2;
};
用两个队列实现栈
https://leetcode-cn.com/problems/implement-stack-using-queues/
class MyStack {
public:
queue<int> q1;
queue<int> q2;
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
if( !q1.empty())
q1.push(x);
else
q2.push(x);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int tmp;
if(!q1.empty()){
while(q1.size()>1){
tmp = q1.front();
q1.pop();
q2.push(tmp);
}
tmp = q1.front();
q1.pop();
return tmp;
}else{
while(q2.size()>1){
tmp = q2.front();
q2.pop();
q1.push(tmp);
}
tmp = q2.front();
q2.pop();
return tmp;
}
}
/** Get the top element. */
int top() {
int tmp;
if(!q1.empty()){
while(q1.size()>1){
tmp = q1.front();
q1.pop();
q2.push(tmp);
}
tmp = q1.front();
q1.pop();
q2.push(tmp);
return tmp;
}else{
while(q2.size()>1){
tmp = q2.front();
q2.pop();
q1.push(tmp);
}
tmp = q2.front();
q2.pop();
q1.push(tmp);
return tmp;
}
}
/** Returns whether the stack is empty. */
bool empty() {
if(q1.empty() && q2.empty())
return true;
else
return false;
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack obj = new MyStack();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.top();
* bool param_4 = obj.empty();
*/
用一个队列实现栈
https://leetcode.com/problems/implement-stack-using-queues/description/
class MyStack {
private:
queue<int> q;
int size ;
public:
/** Initialize your data structure here. */
MyStack() {
size = 0 ;
}
/** Push element x onto stack. */
void push(int x) {
q.push(x);
size++;
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
for(int i=0;i< size-1; i++){
q.push(q.front());
q.pop();
}
int res = q.front();
q.pop();
size--;
return res;
}
/** Get the top element. */
int top() {
for(int i=0;i< size-1; i++){
q.push(q.front());
q.pop();
}
int res = q.front();
q.pop();
q.push(res);
return res;
}
/** Returns whether the stack is empty. */
bool empty() {
if(q.empty()) return true;
else return false;
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack obj = new MyStack();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.top();
* bool param_4 = obj.empty();
*/
P72总结的不错
排序和查找是面试时考察算法的重点。
递归代码很简洁,但是时间和空间消耗很大,另外,递归中有可能很多计算都是重复的,从而对性能带来很大的负面影响。递归的本质是把一个问题分解成多个小问题,如果多个小问题存在相互重叠的部分,就存在重复的计算。除了效率之外,递归还有可能引起更严重的问题:调用栈溢出
通常应用动态规划解决问题时我们都是用递归的思路分析问题,但由于递归分解的子问题中存在大量的重复,因此我们总是用自下而上的循环来实现代码。
P74
斐波那契数列
用递归进行求解有很严重的效率问题!!!!!!!
class Solution {
public:
int Fibonacci(int n) {
if(n==0 || n==1) return n;
int a=0 , b=1 ,tmp;
for(int i=0; i< n-1; i++){
tmp = b;
b = a+b;
a= tmp;
}
return b;
}
};
斐波那契数列的应用----青蛙跳台阶问题
https://www.nowcoder.com/questionTerminal/8c82a5b80378478f9484d87d1c5f12a4?orderByHotValue=1&questionTypes=000100&page=1&onlyReference=false
f
(
n
)
=
f
(
n
−
1
)
+
f
(
n
−
2
)
f(n) = f(n-1) + f(n-2)
f(n)=f(n−1)+f(n−2)
P79
青蛙问题的扩展
https://www.nowcoder.com/questionTerminal/22243d016f6b47f2a6928b4313c85387
相关题目:
斐波那契数列的应用----覆盖大矩形
class Solution {
public:
int rectCover(int number) {
if(number<=0) return 0;
if(number<3) return number;
int a= 1, b=2,tmp;
for(int i=0;i<number-2;i++){
tmp = b;
b = a+b;
a = tmp;
}
return b;
}
};
P79
查找和排序
7种查找算法
https://blog.youkuaiyun.com/chinabhlt/article/details/47420391?utm_source=blogxgwz1
https://www.cnblogs.com/lsqin/p/9342929.html
二分查找平均复杂度
https://bbs.youkuaiyun.com/topics/390884855
二分查找
https://www.nowcoder.com/questionTerminal/28d5a9b7fc0b4a078c9a6d59830fb9b9
插值查找: 基于二分查找,将查找点的选择改为自适应选择
对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比折半查找要好的多。反之,数组中如果分布非常不均匀,那么插值查找未必是很合适的选择。
数据均匀分布情况下,平均复杂度为log(log n)
https://blog.youkuaiyun.com/u010412719/article/details/46335693?utm_source=blogxgwz0
斐波那契查找:在二分查找的基础上根据斐波那契数列进行分割
快速排序
#include<iostream>
#include <vector>
using namespace std;
int partition(vector<int> & a, int start, int end){
int i = start;
int j = end;
int tmp = a[i];
while(i<j){
while(i<j && a[j]>= tmp)
j--;
if(i<j) // 可省
a[i] = a[j];
while(i<j && a[i]<= tmp)
i++;
if(i<j) // 可省
a[j]= a[i];
}
a[i] = tmp;
return i;
}
void quicksort( vector<int> & a, int start, int end){
int index;
if(start<end){
index = partition(a, start, end);
quicksort(a, start, index-1);
quicksort(a,index+1, end);
}
}
int main(){
int n;
cin>>n;
vector<int> a(n);
for(int i=0;i<n;i++) cin>>a[i];
quicksort(a, 0, n-1);
for(int i=0;i<n;i++) {
if(i==0) cout<<a[i];
else cout<<' '<<a[i];
}
cout<<endl;
return 0;
}
P82
旋转数组的最小数字
O(n)复杂度
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
int n = rotateArray.size();
int res = rotateArray[0];
for(int i=1; i< n; i++){
if(rotateArray[i]< res){
res = rotateArray[i];
return res;
}
}
return res;
}
};
O(log n)复杂度
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
int n = rotateArray.size();
if(n==0) return 0;
if(n==1) return rotateArray[0];
int point1 = 0, point2 = n-1;
if(rotateArray[0]<rotateArray[n-1]) return rotateArray[0];
while(true){
if(point2 - point1 == 1) return rotateArray[point2];
int mid = (point1 + point2)/2;
if( rotateArray[point1] == rotateArray[point2] && rotateArray[point1]==rotateArray[mid]){
int minval = rotateArray[point1];
for(int i= point1+1; i< point2;i++){
if(rotateArray[i]<minval)
minval = rotateArray[i];
}
return minval;
}else if(rotateArray[point1]<= rotateArray[mid])
point1 = mid;
else
point2 = mid;
}
}
};
P88
回溯法
矩阵中的路径
class Solution {
public:
bool hasPath(char* matrix, int rows, int cols, char* str)
{ if (!matrix || rows<1 || cols<1 || !str)
return false;
int * visit = new int[rows*cols];
for(int k=0; k< rows*cols; k++)
visit[k]=0;
int index=0;
for(int i=0;i<rows; i++){ // 此处int i = 0, int j=0 要注意
for(int j=0; j< cols;j++){
if(dfs(str,index, i,j , matrix, visit, rows, cols))
return true;
}
}
return false;
}
private:
bool dfs( char * str, int index, int i, int j, char * matrix, int * visit, int rows, int cols){
if( str[index] == '\0' ) return true;
if( i>=0 && i<rows && j>=0 && j<cols && visit[i*cols+j]== 0 && matrix[i*cols+j]==str[index]){
visit[i*cols+j]=1;
if(dfs(str, index+1, i+1,j,matrix, visit,rows,cols) || dfs(str, index+1, i-1,j,matrix, visit,rows,cols) || dfs(str, index+1, i,j+1,matrix, visit,rows,cols) || dfs(str, index+1, i,j-1,matrix, visit,rows,cols)) return true;
else{
visit[i*cols+j]=0;
return false;
}
}
else
return false;
}
};
回溯法
机器人的运动范围
class Solution {
public:
int movingCount(int threshold, int rows, int cols)
{
int row=0, col=0;
vector<vector<int>> visit(rows, vector<int>(cols,0));
int cnt = 0;
dfs(cnt, row, col, threshold, rows, cols, visit);
return cnt;
}
private:
bool isOk(int row, int col, int threshold){
int sum = 0;
while(row){
sum += row%10;
row = row/10;
}
while(col){
sum += col%10;
col = col/10;
}
if(sum<=threshold) return true;
else return false;
}
void dfs( int & cnt, int row, int col, int threshold, int rows, int cols, vector<vector<int>> & visit){
if( row<0 || row>= rows || col<0 || col>=cols) return;
if( visit[row][col]) return ;
if( isOk(row,col,threshold)) { cnt++;
visit[row][col]=1;
dfs(cnt, row+1, col, threshold, rows, cols,visit);
dfs(cnt, row-1, col, threshold, rows, cols,visit);
dfs(cnt, row, col+1, threshold, rows, cols,visit);
dfs(cnt, row, col-1, threshold, rows, cols,visit);
}
}
};
P94
动态规划与贪婪算法
剪绳子
https://leetcode.com/problems/integer-break/
class Solution {
public:
int integerBreak(int n) {
if(n==2) return 1; // 注意
if(n==3) return 2; // 注意
int mem[n+1];
// mem[0]=0; // 注意
mem[1]=1; // 注意
mem[2]=2; // 注意
mem[3]=3; // 注意
int max =0;
for(int i=4; i<=n; i++){
max = 0;
for(int j=1; j<=i/2;j++){
if(mem[j]*mem[i-j] > max)
max = mem[j]*mem[i-j];
}
mem[i]=max;
}
return mem[n];
}
};
P99
位运算
负数比正数多表示一个数0x80000000
把一个整数减1之后再和原来的整数做位与运算,得到的结果相当于把整数的二进制表示中最右边的1变成0
二进制中1的个数
注意: 0x80000000-1 是0x7fffffff
class Solution {
public:
int NumberOf1(int n) {
int cnt = 0;
while(n){
n = (n-1)& n;
cnt++;
}
return cnt;
}
};
相关题目P103
用一条语句判断一个整数是不是2的整数次方
https://leetcode.com/problems/power-of-two/submissions/
输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n
P110
数值的整数次方
自己要全面考虑!不要忽略底数为0,指数为负的错误处理
class Solution {
public:
double Power(double base, int exponent) {
if( fabs(base-0.0)<1e-10 && exponent< 0)
return 0;
int absExponent = exponent;
if(exponent<0){
absExponent = -exponent;
return 1.0/calExp(base, absExponent);
}else
return calExp(base,absExponent);
}
private:
double calExp( double base, int absExponent){
double res = 1.0;
for(int i=1; i<= absExponent;i++)
res *= base;
return res;
}
};
高效解法
class Solution {
public:
double Power(double base, int exponent) {
if( abs(base-0.0)<1e-10 && exponent< 0)
return 0;
int absExponent = exponent;
if(exponent<0){
absExponent = -exponent;
return 1.0/calExp(base, absExponent);
}else
return calExp(base,absExponent);
}
private:
double calExp( double base, int absExponent){
if(absExponent == 0) return 1;
if(absExponent == 1) return base;
double res = calExp(base, absExponent>>1);
res *= res;
if( absExponent & 1) res *= base;
return res;
}
};
P114
打印从1到最大的n位数----大数问题
当n很大的时候,无论是int还是long long,都会溢出
方法一:用字符串模拟数字的加法
bool isEnd(int * digit, int num){
int jinwei = 0,sum;
bool isEndOf = false;
for(int i=num-1;i>=0;i-- ){
sum = digit[i] + jinwei;
if(i==num-1)
sum += 1;
jinwei = sum/10;
if(jinwei==1){
if(i==0) isEndOf = true;
digit[i] = sum%10;
}else{
digit[i] = sum;
break;
}
}
return isEndOf;
}
void printNum(int * digit, int num){
bool isBeginZero = true;
for(int i=0; i< num;i++){
if( isBeginZero && digit[i]!=0)
isBeginZero = false;
if(!isBeginZero)
cout<<digit[i];
}
cout<<endl;
}
void myPrint(int n){
if(n<=0) return;
int digit[n];
for(int i=0; i< n; i++)
digit[i]=0;
while(!isEnd(digit,n)){
printNum(digit,n);
}
}
方法二:全排列
想象成一棵树,每个节点有十个分支
#include <iostream>
using namespace std;
void myPrint(int *a, int n ){
bool isBegin0 = true;
for(int i=0; i< n ;i++){
if(isBegin0 && a[i]!=0)
isBegin0 = false;
if(!isBegin0)
cout<<a[i];
}
if(isBegin0) return ;
cout<<endl;
}
void recursive(int n, int index, int *a){
if(index == n) {
myPrint(a,n);
return ;
}
for(int i=0; i< 10; i++){
a[index] = i;
recursive(n, index+1, a);
}
}
void f(int n){
if(n<1) return ;
int a[n];
for(int i=0; i< n; i++)
a[i]=0;
recursive(n,0,a);
}
int main(){
f(3);
return 0;
}
大数加减乘除
https://www.cnblogs.com/wuqianling/p/5387099.html
两个字符串数字相加
class Solution {
public:
string addStrings(string num1, string num2) {
int len1 = num1.length(), len2 = num2.length();
string res = ""; // 注意是双引号
int loc1 = len1-1, loc2 = len2-1;
int jinwei = 0, sum = 0;
while(loc1>=0 && loc2 >=0){
sum =(num1[loc1]-'0') + (num2[loc2]-'0') + jinwei;
jinwei = sum/10;
res = (char)(sum%10+'0')+res; // 注意 (char)
loc1--;
loc2--;
}
if(loc1>=0){
while(loc1>=0){
sum = (num1[loc1]-'0') + jinwei;
jinwei = sum/10;
res = (char)(sum%10 + '0') + res;
loc1--;
}
}else if(loc2>=0){
while(loc2>=0){
sum = (num2[loc2]-'0') + jinwei;
jinwei = sum/10;
res = (char)(sum%10 + '0') + res;
loc2--;
}
}
if(jinwei == 1)
res = '1'+res;
return res;
}
};
string addStrings(string num1, string num2) {
int len1 = num1.length(), len2 = num2.length();
int len = max(len1, len2)+1;
int add[len]= {0};
int n2[len] = {0};
for(int i= len1-1,j=0; i>=0; i--,j++){
add[j] = num1[i]-'0';
}
for(int i=len2-1,j=0; i>=0; i--,j++){
n2[j]= num2[i]-'0';
}
int jinwei = 0, sum = 0;
for(int i=0; i< len; i++){
add[i] = add[i]+n2[i]+jinwei;
if(add[i]>=10){
jinwei = 1;
add[i] = add[i]-10;
}else{
jinwei = 0;
}
}
if(add[len-1] == 0)
len--;
string res = "";
for(int i=0; i<len; i++)
res = (char)(add[i]+'0')+res; // 注意 +'0'
return res;
}
大数减法
注意减法后的前导0
#include <iostream>
using namespace std;
string mysub( string s1, string s2){
int len1 = s1.length(), len2 = s2.length();
int flag = 0;
string tmp ;
if( len1 < len2){
flag = 1;
tmp = s2;
s2 = s1;
s1 = tmp;
len1 = s1.length();
len2 = s2.length();
}else if( len1 == len2 ){
for(int i=0; i< len1; i++){
if(s1[i]>s2[i]){
break;
}else if(s1[i]==s2[i])
continue;
else{
flag = 1;
tmp = s2;
s2 = s1;
s1 = tmp;
len1 = s1.length();
len2 = s2.length();
break;
}
}
}
int len = len1 ;
int sub[len] = {0};
int n2[len]= {0};
for(int i=len1-1,j=0; i>=0; i--,j++)
sub[j] = s1[i]-'0';
for(int i=len2-1,j=0; i>=0; i--,j++)
n2[j] = s2[i]-'0';
int jiewei = 0;
for(int i=0; i< len; i++){
sub[i] = sub[i]-jiewei - n2[i];
if(sub[i]< 0 ){
jiewei = 1;
sub[i] +=10;
}else{
jiewei = 0;
}
}
string res = "";
if(flag)
res = '-';
for(int i=len-1; i>=0 && sub[i]==0; i--)
len--;
if(len==0)
len = 1;
for(int i=len-1; i>=0; i--)
res = res + (char)(sub[i]+'0');
return res;
}
int main(){
string s2 ="987";
string s1 ="987";
cout<<mysub(s1,s2);
return 0;
}
P119
删除链表的节点
**O(1)**时间内删除链表节点
自己首先想到的是O(n)的方法
方法二:将节点j的内容复制覆盖节点i,接下来让节点i的next指向j的下一个节点,再删除节点j
但是当要删除的节点没有下一个节点的时候,只能顺序遍历了
但是平均时间复杂度是O(1)
P122
删除链表里重复的节点
ListNode* deleteDuplication(ListNode* pHead)
{
ListNode * emptyNode = new ListNode(0);
emptyNode->next = pHead;
ListNode * preNode = emptyNode, * curNode = pHead;
while(curNode!=NULL){
if(curNode->next && curNode->val == curNode->next->val){
int val = curNode->val;
while(curNode && curNode->val == val){
curNode = curNode->next;
}
preNode->next = curNode;
}else{
preNode = curNode;
curNode = curNode->next;
}
}
return emptyNode->next;
}
P124
正则表达式匹配
https://www.cnblogs.com/AndyJee/p/4700373.html
class Solution {
public:
bool match(char* str, char* pattern)
{
if( str==NULL || pattern == NULL) return false;
return matchCore(str,pattern);
}
private:
bool matchCore(char * str, char * pattern){
if( *str =='\0' && *pattern =='\0')
return true;
if(*str!='\0' && *pattern=='\0') // "",".*" 为true
return false;
if( *(pattern+1)=='*'){
if(*str == *pattern || *str!='\0' && *pattern == '.')
return matchCore(str+1, pattern+2) || matchCore(str+1, pattern) || matchCore(str, pattern+2);
else
return matchCore(str, pattern+2);
}else if(*str == *pattern || *str!='\0' && *pattern=='.'){
return matchCore(str+1, pattern+1);
}else {
return false;
}
}
};
P127
表示数值的字符串
class Solution {
public:
bool isNumeric(char* str)
{
if(str == NULL) return false;
bool num = scanInteger(&str);
if(*str == '.'){
str++;
num = scanUnsignedInteger(&str) || num;
}
if(*str == 'e' || *str == 'E'){
str++;
num = num && scanInteger(&str);
}
return num && *str=='\0';
}
bool scanUnsignedInteger( char ** str){
char * start = *str;
while( **str >='0' && **str<='9')
(*str)++;
return *str>start;
}
bool scanInteger(char ** str){
if( **str == '-' || **str == '+')
(*str)++;
return scanUnsignedInteger(str);
}
};