1、给一个数组,元素都是整数(有正数也有负数),寻找连续的元素相加之和为最大的序列。
如:1、-2、3、5、-4、6 连续序列3、5、-4、6的和最大。
如元素全为负数,则最大的和为0,即一个也没有选。
/*
array[] 输入数组
n 数组元素个数
返回最大序列和
*/
int find_max_sum(int array[] , int n)
- int find_max_sum(int array[] , int n)
- {
- int i , max , sum;
- sum = max = array[0];
- for(i = 1 ; i < n ; ++i)
- {
- if(sum < 0)
- sum = array[i];
- else
- sum += array[i];
- if(sum > max)
- max = sum;
- }
- if(max < 0)
- max = 0;
- return max;
- }
int find_max_sum(int array[] , int n) { int i , max , sum; sum = max = array[0]; for(i = 1 ; i < n ; ++i) { if(sum < 0) sum = array[i]; else sum += array[i]; if(sum > max) max = sum; } if(max < 0) max = 0; return max; }
2、给定一个字符串,求出其最长重复子串
例如:abcdabcd
最长重复子串是 abcd,最长重复子串可以重叠
例如:abcdabcda,这时最长重复子串是 abcda,中间的 a 是被重叠的。
直观的解法是,首先检测长度为 n - 1 的字符串情况,如果不存在重复则检测 n - 2, 一直递减下去,直到 1 。
这种方法的时间复杂度是 O(N * N * N),其中包括三部分,长度纬度、根据长度检测的字符串数目、字符串检测。
改进的方法是利用后缀数组
后缀数组是一种数据结构,对一个字符串生成相应的后缀数组后,然后再排序,排完序依次检测相邻的两个字符串的开头公共部分。
这样的时间复杂度为:生成后缀数组 O(N),排序 O(NlogN*N) 最后面的 N 是因为字符串比较也是 O(N)
依次检测相邻的两个字符串 O(N * N),总的时间复杂度是 O(N^2*logN),优于第一种方法的 O(N^3)
- #include <iostream>
- using namespace std;
- #define MAXCHAR 5000 //最长处理5000个字符
- char c[MAXCHAR], *a[MAXCHAR];
- int comlen( char *p, char *q )
- {
- int i = 0;
- while( *p && (*p++ == *q++) )
- ++i;
- return i;
- }
- int pstrcmp( const void *p1, const void *p2 )
- {
- return strcmp( *(char* const *)p1, *(char* const*)p2 );
- }
- int main(void)
- {
- char ch;
- int n=0;
- int i, temp;
- int maxlen=0, maxi=0;
- printf("Please input your string:\n");
- n = 0;
- while( (ch=getchar())!='\n' )
- {
- a[n] = &c[n];
- c[n++] = ch;
- }
- c[n]='\0'; // 将数组c中的最后一个元素设为空字符,以终止所有字符串
- qsort( a, n, sizeof(char*), pstrcmp );
- for(i = 0 ; i < n-1 ; ++i )
- {
- temp=comlen( a[i], a[i+1] );
- if( temp>maxlen )
- {
- maxlen=temp;
- maxi=i;
- }
- }
- printf("%.*s\n",maxlen, a[maxi]);
- return 0;
- }
#include <iostream> using namespace std; #define MAXCHAR 5000 //最长处理5000个字符 char c[MAXCHAR], *a[MAXCHAR]; int comlen( char *p, char *q ) { int i = 0; while( *p && (*p++ == *q++) ) ++i; return i; } int pstrcmp( const void *p1, const void *p2 ) { return strcmp( *(char* const *)p1, *(char* const*)p2 ); } int main(void) { char ch; int n=0; int i, temp; int maxlen=0, maxi=0; printf("Please input your string:\n"); n = 0; while( (ch=getchar())!='\n' ) { a[n] = &c[n]; c[n++] = ch; } c[n]='\0'; // 将数组c中的最后一个元素设为空字符,以终止所有字符串 qsort( a, n, sizeof(char*), pstrcmp ); for(i = 0 ; i < n-1 ; ++i ) { temp=comlen( a[i], a[i+1] ); if( temp>maxlen ) { maxlen=temp; maxi=i; } } printf("%.*s\n",maxlen, a[maxi]); return 0; }
3、字符转换成数字,数字转换成数组
- //字符转换成数字,数字转换成字符
- #include<stdio.h>
- void main()
- {
- int i=0,j=0,x=0,num=0,n=1234;
- char a[]={'1','2','3','4','\0'};
- while(a[i])
- {
- num=num*10+(a[i]-'0');//字符串转换为数字
- i++;
- }
- printf("%d\n",num);
- char temp[5],str[5];
- while(n)
- {
- temp[j]=n%10+'0';//数字转换为字符串
- j++;
- n/=10;
- }
- temp[j]=0;
- j=j-1;
- while(j>=0)
- {
- str[x]=temp[j];//将上面的逆序转为正序
- j--;
- x++;
- }
- str[x]=0;
- printf("%s\n",str);
- }
//字符转换成数字,数字转换成字符 #include<stdio.h> void main() { int i=0,j=0,x=0,num=0,n=1234; char a[]={'1','2','3','4','\0'}; while(a[i]) { num=num*10+(a[i]-'0');//字符串转换为数字 i++; } printf("%d\n",num); char temp[5],str[5]; while(n) { temp[j]=n%10+'0';//数字转换为字符串 j++; n/=10; } temp[j]=0; j=j-1; while(j>=0) { str[x]=temp[j];//将上面的逆序转为正序 j--; x++; } str[x]=0; printf("%s\n",str); }
4、求两个数组的交集
问题: 给你两个排序的数组,求两个数组的交集。
比如: A = 1 3 4 5 7, B = 2 3 5 8 9, 那么交集就是 3 5.
思路:
1. 每一次从B数组中取一值,然后在A数组里逐个比较,如果有相等的,则保存。该算法复杂度为 O(MN). M, N 分别为数组 A B 的长度。
2. 因为A B 都排过序,所以,每一次从B数组取值后,可以利用二分查找看是否在数组A里有B所对应的值,这样复杂度变成了O(N lg M)。 这里,如果N 比 M 大,可以从A中取值,然后在B中判断是否有A的值,这样,复杂度为 O(M lg N)。
3. 利用hashtable. 先把A中的值存在hashtable里,然后对于每一个B中的值,判断是否在A中存在,因为hashtable查找的平均复杂度为 O(1), 所以,整个算法复杂度为O(N), 但是,这里的空间复杂度为 O(M) 。但是,这种方法适合数组比较小的情况。因为如果A数组比较大,hashtable会出现collision的情况,这样,查找的平均复杂度就不再是 O(1)。
本文方法:
因为数组A B均排过序,所以,我们可以用两个“指针”分别指向两个数组的头部,如果其中一个比另一个小,移动小的那个数组的指针;如果相等,那么那个值是在交集里,保存该值,这时,同时移动两个数组的指针。一直这样操作下去,直到有一个指针已经超过数组范围。
- public LinkedList<Integer> intersection(int[] A, int[] B) {
- if (A == null || B == null || A.length == 0 || B.length == 0) return null;
- LinkedList<Integer> list = new LinkedList<Integer>();
- int pointerA = 0;
- int pointerB = 0;
- while (pointerA < A.length && pointerB < B.length) {
- if (A[pointerA] < B[pointerB]) pointerA++;
- else if (A[pointerA] > B[pointerB]) pointerB++;
- else {
- list.add(A[pointerA]);
- pointerA++;
- pointerB++;
- }
- }
- return list;
- }
public LinkedList<Integer> intersection(int[] A, int[] B) { if (A == null || B == null || A.length == 0 || B.length == 0) return null; LinkedList<Integer> list = new LinkedList<Integer>(); int pointerA = 0; int pointerB = 0; while (pointerA < A.length && pointerB < B.length) { if (A[pointerA] < B[pointerB]) pointerA++; else if (A[pointerA] > B[pointerB]) pointerB++; else { list.add(A[pointerA]); pointerA++; pointerB++; } } return list; }
通过上面的算法可以得知,该算法复杂度为O(N + M).