Java算法面试题
题目1:一个数组,让数组的每个元素去除第一个元素,得到的商作为被除数所在位置的新值。
1 @Test 2 public void test1() { 3 int[] array = new int[] { 3, -10, 22, 19, 21, 9, -89 }; 4 5 for (int i = array.length - 1; i >= 0; i--) { 6 array[i] = array[i] / array[0]; 7 } 8 9 for (int i = 0; i < array.length; i++) { 10 System.out.print(array[i] + " "); 11 } 12 13 }
注: 这道题的"陷进"在于如果循环是从数组的第一位元素开始的, 那么经过第一次计算之后,第一位元素的值将变成"1", 那么后面的元素的值都不会再变化. 如果是从数组的末尾开始遍历将不会有这个问题.
题2: 输入两个正整数m和n,求其最大公约数和最小公倍数。
1 @Test 2 public void test2() { 3 int m = 12; 4 int n = 28; 5 6 int max = (m > n) ? m : n; 7 int min = (m > n) ? n : m; 8 9 for (int i = min; i >= 1; i--) { 10 if (max % i == 0 && min % i == 0) { 11 System.out.println("m和n的最大公约数是: " + i); 12 break; 13 } 14 } 15 16 for (int i = max; i < m * n; i++) { 17 if (i % m == 0 && i % n == 0) { 18 System.out.println("m和n的最小公倍数是: " + i); 19 break; 20 } 21 } 22 23 }
题目3:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如:输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。
分析:如果不考虑时间复杂度,我们可以枚举出所有子数组并求出他们的和。不过非常遗憾的是,由于长度为n的数组有O(n^2)个子数组;而且求一个长度为n的数组的和的时间复杂度为O(n)。因此这种思路的时间是O(n^3)。
1 @Test 2 public void test3() { 3 int[] array = new int[] { 1, -2, 3, 10, -4, 7, 2, -5 }; 4 5 int maxSum = 0; 6 int temp = maxSum; 7 for (int i = 0; i < array.length; i++) { 8 temp += array[i]; 9 10 /* 11 * 因为数组有正数,也有负数, 如果元素之和小于0, 12 * 那么需要丢弃这两个元素,即把temp置为0. 13 */ 14 if (temp < 0) { 15 temp = 0; 16 } 17 18 // 如果temp的值比之前的最大和还大,那么需要提升maxSum的值 19 if (temp > maxSum) { 20 maxSum = temp; 21 } 22 23 /* 24 * 最极端的情况: 如果正数后面的那个元素总是负数,而且加起来值总是小于0, 25 * 那么最大和就是数组中值最大的那个元素 26 */ 27 if (maxSum == 0) { 28 for (i = 0; i < array.length; i++) { 29 if (array[i] > maxSum) { 30 31 maxSum = array[i]; 32 } 33 } 34 } 35 36 } 37 38 System.out.println("所有子数组的最大值为: " + maxSum); 39 }
题目4: 将一个字符串进行反转。将字符串中指定部分进行反转。比如将“abcdefg”反转为”abfedcg”。
1 public class test { 2 3 /* 4 * 将一个字符串进行反转。将字符串中指定部分进行反转, 5 * 比如将“abcdefg”反转为”abfedcg” 6 */ 7 8 public static void main(String [] args){ 9 String str = "abcdefg"; 10 11 String newStr = reverseString(str,3,6); 12 System.out.println("Reverse string is: " + newStr); 13 } 14 15 public static String reverseString(String str, int start,int end){ 16 char [] c = str.toCharArray(); 17 char temp ; 18 19 for(int x = start -1, y = end -1; x < y ; x++,y--){ 20 temp = c[x]; 21 c[x] = c[y]; 22 c[y] = temp; 23 } 24 25 return new String(c); 26 } 27 28 29 }
题目5: 输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。句子中单词以空格符隔开。为简单起见,标点符号和普通字母一样处理。
例如输入“I am a student.”,则输出“student. a am I”。
1 /* 2 * 输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。 3 * 句子中单词以空格符隔开。为简单起见,标点符号和普通字母一样处理。 4 * 例如输入“I am a student.”,则输出“student. a am I”。 5 */ 6 7 public class Test { 8 public static void main(String[] args) { 9 String str = "I am a student."; 10 11 String newStr = wordReverse(str); 12 13 System.out.println("Reverse String is: " + newStr); 14 } 15 16 public static String wordReverse(String str){ 17 String [] s = str.split(" "); 18 String temp; 19 for(int x =0,y=s.length-1;x<y;x++,y--){ 20 temp = s[x]; 21 s[x] = s[y]; 22 s[y] = temp; 23 } 24 25 String newStr= ""; 26 for(int i =0;i<s.length;i++){ 27 newStr += s[i]+ " "; 28 } 29 30 return newStr.trim(); 31 } 32 }
题目6: 获取两个字符串中最大相同子串。比如:str1 = "abcwerthelloyuiodef“;str2 = "cvhellobnm"
提示:将短的那个串进行长度依次递减的子串与较长的串比较。
1 public class Test { 2 public static void main(String[] args) { 3 String str1 = "abcwerthelloyuiodef"; 4 String str2 = "cvhellobnm"; 5 6 String newStr = getMaxSubstring(str1,str2); 7 8 System.out.println("The max Substring is: " + newStr); 9 } 10 11 private static String getMaxSubstring(String str1, String str2) { 12 int len1 = str1.length(); 13 int len2 = str2.length(); 14 15 String maxStr = (len1> len2)? str1:str2; 16 String minStr = (len1> len2)? str2: str1; 17 18 int len = minStr.length(); 19 String tempStr = ""; 20 21 for(int i = len; i>0;i--){ 22 for(int j = 0; j <= len - i; j++){ 23 tempStr = minStr.substring(j, j+i); 24 if(maxStr.contains(tempStr)){ 25 return tempStr; 26 } 27 } 28 } 29 30 return null; 31 } 32 }
题目7: 已知有一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n),其中n是大于0的整数,求f(10)的值。
提示: 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
1 /* 2 * 已知有一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n), 3 * 其中n是大于0的整数,求f(10)的值。 4 */ 5 6 public class Test { 7 public static void main(String[] args) { 8 int i = 2; 9 int result = func(i); 10 11 System.out.println("The result is: " + result); 12 } 13 14 private static int func(int n) { 15 int temp; 16 if (n == 0) { 17 temp = 1; 18 } else if (n == 1) { 19 temp = 4; 20 } else { 21 temp = 2 * func(n - 1) + func(n - 2); 22 } 23 24 return temp; 25 } 26 27 }
题目8: for循环的基础,下面的输出结果是什么?
1 @Test 2 public void test4(){ 3 4 int i = 0; 5 for(i++;i++<10;i++); 6 System.out.println("最后i的值为:" + ++i); 7 }
注意: for循环没有循环体.
分析过程:
for循环的基本格式for(A;B;C){}
首先执行A,并且A只执行一次(这个地方容易出错),然后执行B,符合条件就执行循环体,若不存在循环体就直接执行B;不符合条件就直接跳出循环体。
对于这个题目:
首先要明白++i和i++的区别:i++,在执行完后i=i+1;++i,在执行前i=i+1对于这个循环可以这样写for(i=i+1;i<10,i=i+1;i++)开始i=0;
第一次循环:i++;则判断条件是1<10,i=i+1;成立,执行循环体(若加一个输出语句System.out.println(i)则为2),循环体不存在,执行i=i+1此时i为3;
第二次循环:判;断条件是3<10,i=i+1;成立,执行循环体(若加一个输出语句System.out.println(i)则为4),循环体不存在,执行i=i+1此时i为5
第三次循环:则判断条件是5<10,i=i+1;成立,执行循环体(若加一个输出语句System.out.println(i)则为6),循环体不存在,执行i=i+1此时i为7;
第四次循环:则判断条件是7<10,i=i+1;成立,执行循环体(若加一个输出语句System.out.println(i)则为8),循环体不存在,执行i=i+1此时i为9;
第五次循环:则判断条件是9<10,i=i+1;成立,执行循环体(若加一个输出语句System.out.println(i)则为10),循环体不存在,执行i=i+1此时i为11;
第六次循环:则判断条件是11<10,i=i+1;不成立,跳出循环,此时i为12外面的输出语句System.out.println(++i);等价于:i=i+1;System.out.println(i); 因此输出的是13.