数据结构-字符串
作者:互联网
字符串是由若干字符组成的序列。字符串在编程时使用的频率非常高。
C/C++中每个字符串都以\0为结尾,这样我们就能很方便的找到字符串的最后尾部。但由于这个特点,每个字符串中都有一个额外字符的开销,很容易造成字符串越界
例如
char str[10]; strcpy(str,"0123456789");
看起来只有10个字符,但是要正确的复制该字符串,至少需要一个长度为11的数组
为了节省内存,C/C++把常量字符串放到一个单独的内存区域。当几个指针赋值给相同的常量字符串时,他们实际上会指向相同的内存地址。但用常量内存初始化数组,情况却有所不同。
int judge(){ char str1[]="hello world"; char str2[]="hello world"; char* str3="hello world"; char* str4="hello world"; if(str1==str2){ printf("str1 and str2 are same\n"); } else{ printf("str1 and str2 are not same\n"); } if(str3==str4){ printf("str3 and str4 are same\n"); } else{ printf("str3 and str4 are not same\n"); } return 0; }
str1和str2是两个字符串数组,创建地址不同,后来在赋值,所以str1和str2不同
str3和str4是两个指针,无需为他们分配内存,只需要把他们指向hello world在内存中的地址就可以了。由于hello world是常量字符串,他在内存中只有一个拷贝,因此str3和str4只想同一个地址,所以比较str3和str4的值得到的结果相同
面试题5.替换空格
题目:请实现一个函数,把字符串中每个空格替换成%20,例如"We are happy"替换为"We%20are%20happy"
思路:对于空格,#等我们需要将这些特殊符号转换成服务器可以识别的字符。转换的规则是在%后面加上ASCII码的两位十六进制的表示。比如空格ASCII码是32,即十六进制的0x20,因此空格被替换为%20,同理#的ASCII码为35,十六进制0x23,URL中被替换为%23
本题中原来是一个空格字符,替换后变成%,2,0三个字符,那么这个字符串会变长。如果是在原来的字符串上进行替换,就有可能覆盖修改在该字符串后面的内存。如果是创建新的字符串并在新的字符串上进行替换,就可以分配足够的内存。
①从前往后替换,每次添加%20就要把后面的字符往后移动,时间复杂度O(n^2)
②从后往前替换,遍历一遍字符数组,有一个空格就在后面加上2长度,以此计算出要往后的总长度,We are happy长度为14(包括\0)里面有两个空格,因此替换后为18,时间复杂度为O(n)
而在Java里面一切都是对象,是对象的话,字符串肯定就有长度,即然有长度,编译器就可以确定要输出的字符个数,当然也就没有必要去浪费那1字节的空间用以标明字符串的结束了。
使用双标记,一个标记指向被移动的字符,一个标记指向移动目的地,而他们二者的间距就是一个单词的长度
public class spaceReplace { public static void spaceReplace(String strOld,int len){ char[] chs =new char[len]; char[] ch = strOld.toCharArray(); for (int i = 0; i < ch.length; i++) { chs[i] = ch[i]; } int strOldLen = 0; int blackString = 0; if(chs==null || len<=0) { new NullPointerException(); } int i=0; while(chs[i]!='\0'){ strOldLen++; if(chs[i]==' '){ blackString++; } i++; } //将空格转换成%20字符的长度 int strNewLen = strOldLen + blackString*2; if(strNewLen>len){ new ArrayIndexOutOfBoundsException(); } int indexOfOld=strOldLen;//指向'\0' int indexOfNew=strNewLen; while(indexOfOld>0 && indexOfNew>indexOfOld){ if(chs[indexOfOld] == ' '){ chs[indexOfNew--] = '0'; chs[indexOfNew--] = '2'; chs[indexOfNew--] = '%'; } else{ chs[indexOfNew--] = chs[indexOfOld]; } --indexOfOld; } for (char c : chs) { if(c=='\0'){ break; } System.out.print(c); } System.out.println(); } public static void main(String[] args) { String str = "We are happy."; spaceReplace(str,100);//We%20are%20happy. } }
举一反三:
在合并两个数组时,如果从前往后复制每个元素,则需要重复移动元素多次,那么我们可以考虑从后往前复制,这样就能减少移动的次数
拓展题:
有两个排序的数组A1和A2,内存在A1的末尾有足够多的空余空间容纳A2,请实现一个函数,把A2中所有的数字插入A1,并且新数组是排好序的
public class arrayMerge { public static void main(String[] args){ int[] A1,A2; A1=new int[]{1,3,5,7,9}; // A1=new int[]{}; A2=new int[]{2,2,3}; // A2=new int[]{2,4,6,8,10}; arrayMerge(A1,A2,100); } public static void arrayMerge(int[] A1,int[] A2,int num){ int[] res=new int[100]; int len1=A1.length; int len2=A2.length; if(len1==0&&len2!=0){ System.out.println(A2); } else if(len1!=0&&len2==0){ System.out.println(A1); } else if(len1==0&&len2==0){ new NullPointerException(); } int mark1=len1-1,mark2=len2-1; int mark=len1+len2-1; while(mark1>=0&&mark2>=0){ if(A1[mark1]>A2[mark2]){ res[mark--]=A1[mark1--]; } else if(A1[mark1]<=A2[mark2]){ res[mark--]=A2[mark2--]; } } // System.out.print("a"); while(mark1<0&&mark2>=0){ res[mark--]=A2[mark2--]; } // System.out.print("b"); while(mark1>=0&&mark2<0){ res[mark--]=A1[mark1--]; } // System.out.print("c"); for(int i=0;i<len1+len2;i++){ System.out.print(res[i]+" "); } } }
标签:int,A1,--,chs,字符串,数据结构,A2 来源: https://www.cnblogs.com/ak918xp/p/14421224.html