剑指Offer面试题(第三天)面试题4、5

 面试4:二维数组中的查找

** 题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。

** 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该函数。

package Test;

import java.util.Scanner;

public class No4find {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		No4find f = new No4find();
		Scanner in = new Scanner(System.in);
		System.out.println("输入数组的行数和列数:");
		int n = in.nextInt();    //n行
		int m = in.nextInt();	 //m列
		int[][] array = new int[n][m];  //输入二维数组
			//{{1,2,8,9},{2,4,9,12},{4,7,10,13},{6,8,11,15}};
		System.out.println("输入数组的各个元素");
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				array[i][j]=in.nextInt();
			}
		}
		//输出数组元素
		System.out.println("输出数组的各个元素:");
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				System.out.print(array[i][j]+" ");
			}
			System.out.println();
		}
		
		System.out.println("输入要查询的数字:");
		int target = in.nextInt();   //输入为整数
		
		boolean b = f.find(array, target);
		if(b == true) {
			System.out.println("在这个二维数组中有"+target+"这个整数");
		}
		else
			System.out.println("在这个二维数组中有"+target+"这个整数");
	}
	
	
	public boolean find(int[][] array,int target) {
	    //若数组为空则返回false
		if (array == null) {
	        return false;
	    }
	    int row = 0;  				   //行数
	    int column = array[0].length-1;//列数

	    //判断:行数小于数组array的行数  并且  列数大于等于0
	    //*******以右上角为基准进行判断******
	    //亦可以使用左下角为基准进行判断但是其他两个角则不可
	    while (row < array.length && column >= 0) {
	    	//判断:数组中最右边的是否为目标值 
	    	//    若为目标值则返回true  
	    	if(array[row][column] == target) {
	            return true;
	        }
	    	//判断:数组中最右边的若是大于目标值,则列数-1;
	    	//(因为上一个if已经排除了相等的情况)若是小于目标值,则行数+1
	        if(array[row][column] > target) {
	            column--;
	        } else {
	            row++;
	        }
	    }
	    return false;
	}
}

面试题5:替换空格

** 题目:请实现一个函数,把字符串中的每个空格替换成“%20”。

** 例如,输入“We are happy.”,则输出“We%20are%20happy.”。

package Test;

import java.util.Scanner;

public class No5replaceBlank {
/*    面试题5:替换空格
 * ** 题目:请实现一个函数,把字符串中的每个空格替换成“%20”。
 * ** 例如,输入“We are happy.”,则输出“We%20are%20happy.”。
 *        
 *    思路:从后往前复制,只是数组长度会增加,时间复杂度为O(n);
 *    但是从前往后复制,不仅数组长度会增加,时间复杂度也会变为O(n2);
 *    或者可以使用StringBuilder、StringBuffer类对字符串进行操作
 * */
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		No5replaceBlank rb = new No5replaceBlank();
		
		Scanner in = new Scanner(System.in);
		System.out.println("输入一个字符串:");
		StringBuffer s = new StringBuffer(in.nextLine());   //输入一行字符串
		
		System.out.println("将空格转换为20%的结果(StringBuilder,时间复杂度O(n)+空间复杂度O(n)):");
		System.out.println(rb.replaceBlank(s));
		System.out.println("将空格转换为20%的结果(从后往前进行赋值,时间复杂度O(n)):");
		System.out.println(rb.replaceBlank1(s));
	}
	
	//方法一:使用StringBuffer+StringBilder
	//      构建一个新的空间  将数据复制进去  从前到后的顺序即可
	public String replaceBlank(StringBuffer s) {
		if(s == null) return null;
		
		StringBuilder sb = new StringBuilder();
		 //从后向前复制,遇到空格就加%20到sb,不是,就直接加原来的字符
		//charAt(int i)方法----字符串中第i个字符
		for(int i=0;i<s.length();i++) {
			if(String.valueOf(s.charAt(i)).equals(" ")) {
				sb.append("%20");
			} 
			else {
				sb.append(s.charAt(i));
			}
			
		}
		
		return String.valueOf(sb);  
		//将StringBuilder类的对象sb转换为String类型
		
	}
	
	//方法二:从后往前复制,只是数组长度会增加,时间复杂度为O(n);
	//      先遍历一遍字符串,查看一下空格数,计算出替换后的长度 :原来的+2*空格数
	//      在从后面开始往前进行复制和替换   front指向原始字符串的末尾(/0前一个),tail指向替换后的字符串的末尾
	//      front逐个把它指向的字符复制到tail所指向的位置,若是碰到空格则在tail处添加02%,否则就一直赋给tail	
	//		直到front=0之后(到达了字符串的尽头)或者front==tail(首尾相遇也表示空格都已填满),就结束
	public String replaceBlank1(StringBuffer s) {
		if(s == null) return null;
		int blankNum = 0;  //计算空格数
		for(int i=0;i<s.length();i++) {
			if(s.charAt(i)==' ') {
				blankNum++;
			}
		}
		
		int front = s.length()-1;
		int tail = s.length()-1+2*blankNum;
		s.setLength(tail+1);  // +1是指    加上String后边的/0
		while(front != tail) {
			if(s.charAt(front)==' ') {
				s.setCharAt(tail--,'0');
				s.setCharAt(tail--,'2');
				s.setCharAt(tail--,'%');
			}else {
				s.setCharAt(tail--,s.charAt(front));
				
			}
			front--;
			
		}
		return String.valueOf(s);
		
	}
	

}

补充一些可能有用的知识点:

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Java中String、StringBuffer与StringBuilder之间的区别

转载:https://blog.csdn.net/Mecera/article/details/80545395

1.String  含义为引用数据类型,是字符串常量.是不可变的对象,(显然线程安全)在每次对string类型进行改变的时候其实都等同与生成了一个新的String对象.然后指针指向新的String对象,所以经常改变内容的字符串最好不使用String,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了之后.JVM的垃圾回收(GC)就会开始工作,对系统的性能会产生影响            

扫描二维码关注公众号,回复: 5653377 查看本文章

2.StringBuffer   线程安全可变字符序列:对StringBuffer对象本身进行操作,而不是生成新的对象.所以在改变对象引用条件下,一般推荐使用StringBuffer.同时主要是使用append和insert方法,  

 3.StringBuilder   线程不安全可变字符序列.提供一个与StringBuffer兼容的API,但不同步.设计作为StringBuffer的一个简易替换,用在字符缓冲区被单个线程使用的时候.效率比StringBuffer更快

--------------------------------------------------------------------------------

Java中String、StringBuffer与StringBuilder之间的区别:    

a.执行速度:StringBuilder > StringBuffer > String    

b.线程安全:String、StringBuffer线程安全.StringBuilder线程不安全    

c.String适用与少量字符串操作      

   StringBuilder适用单线程下在字符缓冲区下进行大量操作的情况  

   StringBuffer使用多线程下在字符缓冲区进行大量操作的情况
 

另外可以看一下这个 介绍三者很详细:

地址:http://www.cnblogs.com/dolphin0520/p/3778589.html

---------------------------------------------------------------------------------------------------------------------------------------

转换为String类型的几种方法:(String)、toString、String.valueOf()

(String)、toString、String.valueOf()的区别

转载:https://www.cnblogs.com/xhyouyou/p/6014367.html

常用的方法有(String)要转换的对象,Object#toString(),String.valueOf(Object)等。

  • (String)
  • 这是标准的类型转换,将object转成String类型的值。使用这种方法时,需要注意的是类型必须能转成String类型。因此最好用instanceof做个类型检查,以判断是否可以转换。否则容易抛出CalssCastException异常。此外,需特别小心的是因定义为Object 类型的对象在转成String时语法检查并不会报错,这将可能导致潜在的错误存在。这时要格外小心。如: 

    1

    2

    Object obj = new Integer(100);

    String strVal = (String)obj;

    在运行时将会出错,因为将Integer类型强制转换为String类型,无法通过

    

  • toString
  • 在这种使用方法中,因为java.lang.Object类里已有public方法.toString(),所以对任何严格意义上的java对象都可以调用此方法。但在使用时要注意,必须保证object不是null值,否则将抛出NullPointerException异常。采用这种方法时,通常派生类会覆盖Object里的toString()方法。

        

    

  • String.valueOf
  • 这个方法是静态的,直接通过String调用,可以说是完美,只是平时不习惯这样写而已,这样的实现避免了前面两个的不足和缺点。首先来看看他内部的实现机制:
  • public static String valueOf(Object obj){    
    
        return (obj==null) ? "null" : obj.toString()
    
    };

    在内部就是做了为空的判断的,所以就不会报出空指针异常。  

    从上面的源码可以很清晰的看出null值不用担心的理由。但是,这也恰恰给了我们隐患。我们应当注意到,当object为null 时,String.valueOf(object)的值是字符串”null”而不是null!!!在使用过程中切记要注意。

    试想一下,如果我们用

  • if(String.valueOf(object)== null){    
    
        System.out.println(“传入的值是null!”);
    
    }

    这样的语句将可能会发生什么问题。再想一下,向控制台输出时,在视觉上如下语句在执行的结果上有什么不同:

    Object obj = null;
    System.out.println(String.valueOf(obj) + "->此处null的类型是" + String.valueOf(obj).getClass());
    System.out.println(obj);

    我们看到的输出将是一模一样的东西:null,但它们意义相同吗?

        

猜你喜欢

转载自blog.csdn.net/weixin_43137176/article/details/88774298