时间复杂度为O(n),空间复杂度为O(1)

时间复杂度为O(n),空间复杂度为O(1)的典型问题搜集:

对换思想;

一次遍历求得统计信息,二次遍历算法求解;

利用固定大小的空间存放统计信息;

利用已知子问题的解...



1.字符串左移,void*pszStringRotate(char *pszString, intnCharsRotate),比如 ABCDEFG,移3 位变 DEFGABC,要求空间复杂度 O1),时间复杂度 On

(分析:分析与解法

假设原数组序列为abcd1234,要求变换成的数组序列为1234abcd,即循环右移了4,比较之后,不难看出,其中有两段的顺序是不变的:1234和abcd,可把两段看成两个整体。右移K位的过程就是把数组的两部分交换一下。变换过程通过以下步骤完成:

 

1.逆序排列 abcd: abcd1234-> dcba1234; //前n-k位逆序(对换)

2.逆序排列 1234:dcba1234-> dcba4321;//后k为逆序

3.全部逆序dcba4321->1234abcd。//全体逆序

 

2. 对n个数排序,要求时间复杂度为O(n),空间复杂度为O(1)

假定你的数字范围在0到65535范围之内,定义一个数组count[65536](这个空间是常量,和n无关,所以是O(1) ),初值全部为0。

那么假设有下面这些数字:

100 200 300 119 0 6

...

那么对于每个这个数字,都做在count中记录一下:

100 => count[100]++

200 => count[200]++

300 => count[300]++

119 => count[119]++

0 => count[0]++

6 => count[6]++

...

最后,遍历一边所有这些数字就可得到0~65535每个数字的个数(在count数组中),然后再顺序遍历count数组,count[n] = m,则输出m个n,(比如说有count[3] = 2, 那么说明有2个数字3),依次输出,最后可得结果。第一次遍历是O(n),第二次遍历是O(1),为常量,所以最后的时间复杂度为O(n),而空间复杂度为O(1)

 

3.1删除字符串中的连续空格时间复杂度为O(n),而空间复杂度为O(1)

(分析:设置两个指针,一个用于遍历,一个用于结果的拷贝。后面的元素写入前面对应的位置

Eg:


 

char* trim(char* a) 

{//i指针拷贝后面或者当前元素到当前位置,j遍历数组元素结点

   int i=-1,j=0; 

   for (;a[j]!='\0';j++) 

   { 

       if (a[j]==a[j+1] && a[j+1]==' ') 

       { 

           //skip more than one blank  

           while (a[j]==' ') 

           { 

                ++j; 

           } 

           --j;// go back to the last blank  

       } 

       a[++i]=a[j]; 

   } 

   a[++i]='\0'; 

   return a; 

3.2 替换空格

问题:请实现一个函数,把字符串中的每个空格替换成“%20”。例如输入“We are happy.",则输出”We%20are%20happy."

分析:在空间复杂度尽可能低的情况下,不允许开辟一个新的数组来存放替换空格后的字符串。如果从前往后替换字符串,那么保存在空格后面的字符串肯定会被覆盖。假设字符串的长度为n。对每个空格字符,需要移动后面O(n)个字符,因此对含有O(n)个空格字符的字符串而言总的时间复杂度是O(n^2),明显不可取。

从后往前进行替换,时间复杂度降为O(n)。

(1)首先遍历一遍字符串,找出字符串的长度以及其中的空格数

(2)根据原字符串的长度和空格数求出最后新的字符串的长度

(3)设置两个指针分别指向原字符串和新字符串的末尾位置

(4)如果原字符串的指针指向的内容不空,则将内容赋值给新指针指向的位置;否则从新指针开始向前赋值02%

(5)直到两个指针相等时表明字符串中的所有空格已经替换完毕

 

 

4.判断一个数组中是否有重复元素  要求时间复杂度O(n),空间复杂度O(1)

数组map的思想

  要求空间复杂度为O(1),那么可以申请常数大小的空间,由于int最大表示范围为65536,我们可以直接申请65536大小的数组b。

  将原数组中的a[i],通过b[a[i]]++,来进行计数,如果值超过1,则表明有重复

  优点:

  申请空间比较大

5.(联系4)统计数组中不同元素出现的次数(时间复杂度O(n),空间复杂度o(1)

 

6.数对之差的最小值

题描述:在数组中,数字减去它右边的数字得到一个数对之差。求所有数对之差的最大值。例如在数组{2, 4, 1, 16, 7, 5, 11, 9}中,数对之差的最大值是11,是16减去5的结果。

     思路:这又是一道动态规划的题目,这是我能想到的最好方法,时间复杂度为O(n)。假设f[i]表示数组中前i+1个数的解,前i+1个数的最大值为m[i]。则有下列式子。

    f[i] = max(f[i-1], m[i-1]- a[i]), m[i] = max(m[i-1],a[i])


7.寻找超过一半的元素

1.  /*n个字符的数组,只有一个元素出现的次数最多,找出该元素*/  

2.  char FindIt(char a[],int n)  

3.  {  

4.    char ch;  

5.    int times=0;  

6.    int i;  

7.  for(i=0;i<n;i++)  

8.  {  

9.      if(times==0)/*计数清零,从本次开始选取新的字符*/  

10.     {  

11.         ch=a[i];  

12.         times=1;  

13.     }  

14.     else if(ch==a[i])/*找到相同的计数加1*/  

15.             times++;  

16.       else/*与备选的字符ch不同,计数-1.做一次抵消。只有次数最多的才会保留到最后*/  

17.             times--;  

18. }  

19. return ch;  

20. }  

21.   


  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值