面试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)就会开始工作,对系统的性能会产生影响
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,但它们意义相同吗?
- 总结:
这三者的使用,个人觉得应该使用String.valueOf()的方式。这样的使用安全可靠,不会带来异常。 - 参考自:http://blog.csdn.net/springk/article/details/6414017