1.递归合并有序链表
2.寻找二叉树中两个节点的最近的公共祖先
3.进制算法转换
4.大小写转换
5.求两同长数组的中位数问题
6.求数组的第k大的数字
7. 最接近S的中位数的k个数
1.递归合并有序链表
Node* mergAction(Node* head1,Node *head2) { Node *p=NULL; if(head1==NULL&&head2==NULL) return p; else if(head1==NULL) return head2; else if(head2==NULL) return head1; else { if(head1->data < head2->data) { p = head1; p->next = mergAction(head1->next,head2); } else { p = head2; p->next = mergAction(head1,head2->next); } return p; } }
class Node { Node * left; Node * right; Node * parent; }; /*查找p,q的最近公共祖先并将其返回。*/ Node * NearestCommonAncestor(Node * p,Node * q);
Node * NearestCommonAncestor(Node * root,Node * p,Node * q) { Node * temp; while(p!=NULL) { p=p->parent; temp=q; while(temp!=NULL) { if(p==temp->parent) return p; temp=temp->parent; } } }
解法2:算法思想:如果一个节点的左子树包含p,q中的一个节点,右子树包含另一个,则这个节点就是p,q的最近公共祖先。
/*查找a,b的最近公共祖先,root为根节点,out为最近公共祖先的指针地址*/ int FindNCA(Node* root, Node* a, Node* b, Node** out) { if( root == null ) { return 0; } if( root == a || root == b ) { return 1; } int iLeft = FindNCA(root->left, a, b, out); if( iLeft == 2 ) { return 2; } int iRight = FindNCA(root->right, a, b, out); if( iRight == 2 ) { return 2; } if( iLeft + iRight == 2 ) { *out = root; } return iLeft + iRight; } void main() { Node* root = ...; Node* a = ...; Node* b = ...; Node* out = null; int i = FindNCA(root, a, b, &out); if( i == 2 ) { printf("Result pointer is %p", out); } else { printf("Not find pointer"); } }
3.进制算法转换
编程实现将十进制的整数转化成任意进制的整数,用户输入
一个十进制数R和想要转化的进制数X,程序输出转换后的X进制的整数。
算法思想:将十进制数R与进制X取模,即R%X的值作为X进制整数的倒数第一位,
然后使R等于R/X,再取R%X的值作为X进制整数的倒数第二位......依次类推,直
到最后R/X=0为止。
#include <iostream> #include <string> using namespace std;
/*将一个整型数字转化成字符型数字,例如 8->'8',12->'c'*/ void numToChar(char &num) {
/*num是0到9之间的数字*/ if(num<=9&&num>=0) { num+=48; }
/*num是10到15之间的数字*/ else { switch(num) { case 10:num='A'; case 11:num='B'; case 12:num='C'; case 13:num='D'; case 14:num='E'; case 15:num='F'; } } }
/*进制转化函数——r表示需要被转化的十进制数,x表示进制(1<x<17)*/ void decimalTransmit(int r,int x) { string result;//保存x进制数 char temp; while(r>0) { temp=r%x; numToChar(temp); result+=temp; r=r/x; } /*输出转化后的x进制整数*/ for(int i=result.size()-1;i>=0;i--) cout<<result[i]; cout<<endl; }
int main() { int R,X; cout<<"请输入一个十进制数和要转化的进制(用空格作为间隔符):"; cin>>R>>X; decimalTransmit(R,X); return 0; }
还有一个mton的算法,很漂亮,但是遗憾的是只支持1~10进制的转换。
void m2n(int m, char* mNum, int n, char* nNum) { int i = 0; char c, *p = nNum; //这是一个考察地方,是否能用最少乘法次数。 while (*mNum != '\0') i = i*m + *mNum++ - '0'; //辗转取余 while (i) { *p++ = i % n + '0'; i /= n; } *p-- = '\0'; //逆置余数序列 while (p > nNum) { c = *p; *p-- = *nNum; *nNum++ = c; } }
#define to_uppercase(ch) ((ch) - 'a' + 'A') #define to_lowercase(ch) ((ch) - 'A' + 'a')
以后记不住,记住带入特殊值作检验:
‘a’->‘A’ ‘a’ - ‘a’ + ‘A’
‘A’->‘a’ ‘A’ - 'A' + 'a'
貌似这么简答我都在考场上想了很久,足见状态之差
5.求两同长数组的中位数问题
中位数问题:设X[0:n-1]和Y[0:n-1]为两个数组,每个数组中含有N个 已经排好序的数。试设计一个O(logn)时间算法,找出X和Y的2N个数的中位数。
第一行: n,为x和y数组的元素个数
第二行: x数组的n个数,用空格分隔
第三行: y数组的n个数,用空格分隔
#include <stdio.h> #include <stdlib.h> int main() { //两个数组 int len = 0; //获取数组的长度 scanf("%d", &len); //动态分配数组 int * a; int * b; a = (int *)malloc(sizeof(int) * len); b = (int *)malloc(sizeof(int) * len); //获取每个数组的元素 for(int i=0; i < len; i++) { scanf("%d", &a[i]); } for(int j=0; j < len; j++) { scanf("%d", &b[j]); } //两个数组的左右端点的坐标 int aLeft = 0; int aRight = len - 1; int bLeft = 0; int bRight = len - 1; //两数组中间坐标 int aMid = 0; int bMid = 0; //迭代循环 while(true) { //printf("a left is %d right is %d, and b left is %d right is %d.\n", aLeft, aRight, bLeft, bRight); // 如果两个数组都只剩下两个元素,则中位数一定在其中 if( (aRight - aLeft) == 1 && (bRight - bLeft) == 1) { // 输出第一行的最大一个值 printf("%d ", (a[aLeft]>=b[bLeft])?a[aLeft]:b[bLeft]); // 输出第一行的最小一个值 printf("%d\n", (a[aRight]<=b[bRight])?a[aRight]:b[bRight]); // 结束循环 break; } else { // 求解各个数组的中值 aMid = (int)((aLeft + aRight)/2); bMid = (int)((bLeft + bRight)/2); // 如果A中值小于B中值 if(a[aMid] < b[bMid]) { // 如果B中现存的数列是偶数个,右边值加一 if((bLeft + bRight + 1) % 2 == 0) { aLeft = aMid; bRight = bMid + 1; } else { aLeft = aMid; bRight = bMid; } } // 如果B中值小于A中值 else { // 如果A中现存的数列是偶数个,右边值加一 if((aLeft + aRight + 1) % 2 == 0) { aRight = aMid + 1; bLeft = bMid; } else { aRight = aMid; bLeft = bMid; } } } } return 0; }
#include <cstdlib> #include <iostream> /** *求一个数组中的第k大数 *基本思想: *以最后一个元素x为轴,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况: *1.Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数; *2.Sa中元素的个数大于等于k,则返回Sa中的第k大数。 *时间复杂度近似为O(n) */ using namespace std; void exchange(int &a,int &b) { int temp; temp=a; a=b; b=temp; } //快排的partition函数 int partition(int *a,int l,int r) { int i=l-1,j=l; int x=a[r]; int temp; for(j=l;j<r;j++) { if(a[j]>=x) //把比x大的数往前放 { exchange(a[j],a[i+1]); i++; } } exchange(a[r],a[i+1]); return i+1; } int k_element(int *a,int l,int r, int k) { if(l>=r) return a[l]; int q=partition(a,l,r); if(q==k-1) return a[q]; else if(q>=k) return k_element(a,l,q-1,k); //Sa中元素个数大于等于k else return k_element(a,q+1,r,k-(q+1)); //Sa中元素个数小于k } int main(int argc, char *argv[]) { int a[100]; int length; cin>>length; for(int i=0;i<length;i++) cin>>a[i]; cout<<k_element(a,0,length-1,4)<<endl; system("PAUSE"); return EXIT_SUCCESS; }