第七十一题:求a的b次方
思路1:循环乘积
思路2:half=a^(b/2) 即a^b=half*half,复杂度从O(n)降为O(logn)
PS:除以二可以用>>1代替,判断可以否整除2可以用 & 1代替,位操作提高系效率。
double helper(double base,int power){ if(power==1)return base; if(power==-1)return 1/base; if(power%2==0){ double half=helper(base,power/2); return half*half; }else{ double half=helper(base,(power-1)/2); return half*half*base; } } double helper2(double base,int power){ if(power==1)return base; if(power==-1)return 1/base; double half=helper(base,power/2);//可改进为power>>1右移一位 return ((power%2==0)?1:base)*half*half;//可改进为power & 1==0表示末尾为0可以整除2 }
第七十二题:单例设计
思路:用静态static变量记录实例个数,私有化构造函数。用static函数接口来调用构造函数
PS:类中静态成员必须在类以外初始化
class single{ static int count;//只声明没定义 single(){}//必须要加大括号 不然没定义 public: static single* create(){ if(single::count==0){ single::count++; return new single; }else return NULL; } void del(); }; int single::count=0;//类中静态成员必须在类以外初始化,定义
第七十三题:求最长回文
思路:依次从后往前扫,复杂度O(n^2)。答案说可以用后缀树提高效率,最后还是没弄懂。
int helper(char *str){ int len=strlen(str); int maxlen=0; for(int i=0;i<len;++i){ int tmp=0; int head=i; for(int j=len-1;j>=head;--j){ if(head==j){ tmp++; head++; } else if(str[head]==str[j]){ tmp+=2; head++; } else{ tmp=0; head=i; } } if(tmp>maxlen)maxlen=tmp; } return maxlen; }
第七十四题:数组中出现次数超过数组长度一半的数
思路:因为出现次数超过一半,因此只要把其他的数和那个数一起抵消掉,剩下的肯定就是所要找的数。因此扫描数组,遇上不同的就同时删除。其实不用真的删除数组中的数,只要用一个cnt记录当前数字的量,遇到不同的减一,遇到相同加一,cnt为0了就令下一个数字为当前数字。
int helper(int *num,int n){ int cnt=0; int x; for(int i=0;i<n;++i){ if(cnt==0){ x=num[i]; cnt++; }else if(num[i]==x)cnt++; else cnt--; } return x; }
第七十五题:二叉树最低公共父节点
思路:左右子树同时存在目标的话,就是该节点。因此使用递归查找子树是否存在目标,如果存在,利用返回值往上传。
BinaryTreeNode* helper(BinaryTreeNode *root,BinaryTreeNode *one,BinaryTreeNode *two){ if(root==one|| root==two)return root; if(root==NULL)return NULL; BinaryTreeNode *left=helper(root->m_pLeft,one,two); BinaryTreeNode *right=helper(root->m_pRight,one,two); if(left!=NULL && right!=NULL)return root; else if(left==NULL && right==NULL)return NULL; else if(left!=NULL)return left; else return right; }
第七十六题:复制复杂链表
思路:1、新建节点,插在原节点后,如上图。2、建立新节点的偏移跳转。3、分离新旧链表
第七十九题:单链表排序
思路:由于单链表不能随机存取,用快排不方便,因此单链表最快的排序方法是归并排序。
PS:归并排序复杂度logN,而且是稳定排序(元素相对位置不改变)。核心思想是把两个有序数组合并。当递归到子数组长度为1时就已经有序了。
//合并两个有序数组 void merge(int *a,int m,int *b,int n,int *buf){ int i,j,k; i=j=k=0; while(i<m && j<n){ if(a[i]<b[j])buf[k++]=a[i++]; else buf[k++]=b[j++]; } while(i<m)buf[k++]=a[i++]; while(j<n)buf[k++]=b[j++]; //先合并到buf,再复制回原数组,避免重复新建空间 for(int i=0;i<n+m;++i)a[i]=buf[i]; } void mergesort(int *c,int n,int *buf){ if(n==1)return; int *a=c,*b=c+n/2; int na=n/2,nb=n-n/2; mergesort(a,na,buf); mergesort(b,nb,buf); merge(a,na,b,nb,buf);//使用buf } void merge_sort(int *c,int n){ int buf[n]; mergesort(c,n,buf); }