数据结构-字符串

字符串是由若干字符组成的序列。字符串在编程时使用的频率非常高。

C/C++中每个字符串都以为结尾,这样我们就能很方便的找到字符串的最后尾部。但由于这个特点,每个字符串中都有一个额外字符的开销,很容易造成字符串越界

例如

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
");
  }
  else{
    printf("str1 and str2 are not same
");
  }
  
  if(str3==str4){
    printf("str3 and str4 are same
");
  }
  else{
    printf("str3 and str4 are not same
");
  }
  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(包括)里面有两个空格,因此替换后为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]!=''){
            strOldLen++;
            if(chs[i]==' '){
                blackString++;
            }
            i++;
        }
        //将空格转换成%20字符的长度
        int strNewLen = strOldLen + blackString*2;
        if(strNewLen>len){
            new ArrayIndexOutOfBoundsException();
        }

        int indexOfOld=strOldLen;//指向''
        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==''){
                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]+" ");
        }
    }
}

原文地址:https://www.cnblogs.com/ak918xp/p/14421224.html