编程之美续
看完编程之美后看很多题,都会发现原来只是里面一些题目的变种(也大概因为看的是微软的笔试题吧。。),把原先的算法稍微一改,就变成了题目的解法,还是挺带劲的。
1. 反转单向链表:给出单向链表的头指针,要求把链表反转过来。
struct ListItem{int value;struct ListItem* next;};ListItem* reverse( ListItem* pHead ){//如果链表为空或只有一个元素,直接返回if( pHead==NULL || pHead->next == NULL )return pHead;ListItem* pNext=pHead->next; ListItem* pCatch=pNext->next;pHead->next = NULL;while( pCatch != NULL ){pNext->next = pHead;pHead = pNext;pNext = pCatch;pCatch = pCatch->next;}pNext->next = pHead;pHead = pNext;return pHead;}ListItem* reverse( ListItem* pHead, ListItem* pStart ){//改动1:如果链表为空或只有一个元素,或pStart指向pHead,直接返回if( pHead==NULL || pHead == pStart || pStart == NULL )return pHead;ListItem* pNext=pHead->next; ListItem* pCatch=pNext->next;pHead->next = pStart->next;//改动2:末尾原为NULL,现为pStart->next(下同)while( pCatch != pStart->next ){pNext->next = pHead;pHead = pNext;pNext = pCatch;pCatch = pCatch->next;}pNext->next = pHead;return pStart;}int gcd( int a, int b ){int base = 1;while( a!= b ){if( a&0x01 == 0 ){if( b&0x01 == 0 ){base <<= 1;a >>= 1;b >>= 1;}elsea >>= 1;}else{if( b&0x01 == 0 )b >>= 1;else{if( a> b )a -= b;else b -= a;}}}return base*a;}//求多个数的最大公约数,函数接收数组的指针及数组大小int ngcd1( int* array, int size ){//递归求解if( size == 1 )return *array;return gcd( array[size-1], ngcd1( array, size-1 ) );}//继续使用上面的gcdint ngcd3( int* array, int size ){if( size == 1 )return array[0];int curGcd = gcd( array[0], array[1] );int i=2; //当出现当前最大公约数为1时,无需再求剩下的元素的公约数了while( curGcd != 1 && i<size )curGcd = gcd( curGcd, array[i++] );return curGcd;}int ngcd2( int* scrArray, int size ){int minIndex = 0;while( minIndex<size && !scrArray[minIndex++] );minIndex--;//if all elements are 0if( scrArray[minIndex] == 0 )return 0;int* array = new int[size];for( int i=0; i<size; i++ )array[i] = scrArray[i];int res = 1;//minElem 为非零元素中最小的那个int minElem = array[minIndex];for( int i=minIndex+1; i<size; i++ )if( array[i] && minElem > array[i] ){minElem = array[i];minIndex = i;}//找到当前最小非零元素,将其交换到第一个元素的位置array[minIndex] = array[0];array[0] = minElem;while( minElem>1 ){for( int i=1; i<size; i++ ){array[i] = array[i]%array[0];if( array[i] && array[i]<minElem ){minIndex = i;minElem = array[i];}}//如果minElem并没有改变,说明当前除了array[0]之外其余均为0了if( minElem == array[0] ){res = minElem;break;}array[minIndex] = array[0];array[0] = minElem;}delete[] array;return res;}char* reverse( char* str ){//总共遍历了str两次,一次用于计算strlen,一次用于逐个交换。//使用到的额外的空间是两个用于遍历str的指针,一前一后int len = strlen(str);char* beg = str, *end = str+len-1;while( end > beg ){*end ^= *beg;*beg ^= *end;*end ^= *beg;end--;beg++;}return str;}//end是有效下标char* __reverse( char* str, int beg, int end ){while( end>beg ){str[end] ^= str[beg];str[beg] ^= str[end];str[end] ^= str[beg];end--;beg++;}return str;}char* reverseByWord( char* str ){int len = strlen( str );str = __reverse( str, 0, len-1 );int iStart =0, iEnd = 0;for( int i=0; i<len; i++ ){if( str[i] == ' ' ){iEnd = i-1;__reverse( str, iStart, iEnd );iStart = i+1;}else if( !((str[i]>='A'&&str[i]<='Z') or (str[i]>='a'&&str[i]<='z')) )iStart = i+1;}__reverse( str, iStart, len-1 );return str;}int josephus( int n, int m ){int r = 1;for( int i=2; i<=n; i++ ){r = (r+m)%i;if( r == 0 )r = i;}return r;}int josephus( int n, int m, int k ){int r = josephus( n, m );return (r+k-1)%n;}