算法也属于常见面试内容之一,但基本不会超过《剑指offer》的范围,在此附上一篇简书上整理的内容:
第二版java解法
常见的面试题包括以下几类:字符串操作,文件输入输出流及统计,矩阵操作,单例模式等。
含有左右括号的字符串匹配的题目及代码如下:
给定一个字符串,其中的字符只包含三种括号:花括号{ }、中括号[ ]、圆括号( ),即它仅由 “( ) [ ] { }” 这六个字符组成。设计算法,判断该字符串是否有效,即字符串中括号是否匹配。括号匹配要求括号必须以正确的顺序配对,如 “{ [ ] ( ) }” 或 “[ ( { } [ ] ) ]” 等为正确的格式,而 “[ ( ] )” 或 “{ [ ( ) }” 或 “( { } ] )” 均为不正确的格式。
/**
* 栈的先入后出,非常适合作为括号匹配的对象 思路:将所有的左括号类型入栈,出现一个匹配的右括号即出栈
* 如果最后栈为空则完全匹配;如果最后栈非空则不匹配
*/
public class MatchString {
public static boolean isMatchStr(String s){
if(s==null || s.length()<1) return false;
Stack stack=new Stack<>();
char c;
boolean flag=true;
int cnt=0;
for(int i=0;i// 入栈规则
if(c=='(' || c=='[' || c=='{'){
stack.push(c);
cnt++;
continue;
}
// 过滤非括号的无关字符串
if(c!='(' && c!='[' && c!='{' && c!=')' && c!=']' && c!='}') continue;
// 出栈规则
if(stack.isEmpty()||!isMatch(c,stack.peek())) return false;
if (!stack.isEmpty() && isMatch(c, stack.peek())) {
stack.pop();
cnt++;
continue;
}
}
if(!stack.isEmpty()) return false;
return flag;
}
private static boolean isMatch(char right, char left) {
if(right==')')
return left=='(';
if(right==']')
return left=='[';
if(right=='}')
return left=='{';
return false;
}
public static void main(String[] args) {
String s1="({{123}})";
String s2="}}}}}{{{{";
String s3="((111111({{}}})))";
System.out.println(isMatchStr(s1));
System.out.println(isMatchStr(s2));
System.out.println(isMatchStr(s3));
}
}
字符串反转在剑指offer上也能找到类似的题目,反转单词顺序:
输入一个英文句子,翻转单词顺序,单词内字符不翻转,标点符号和普通字母一样处理。例如输入输入“I am a student.”,则输出“student. a am I”。
/**
* 先对所有字符串进行反转,之后按照空格分隔开,再对单个单词进行反转。
*/
public class ReverseWordsInSentence {
public static String reverseStr(String str){
if(str==null || str.length()<=1) return str;
Stack stack=new Stack<>();
StringBuffer stringBuffer=new StringBuffer();
for(int i=0;ifor(int i=0;i" ");
stringBuffer.setLength(0);
for(int i=0;i" ");
}
return stringBuffer.toString();
}
public static String reverseWord(String s){
StringBuffer stringBuffer=new StringBuffer();
if(s==null || s.length()<=1) return s;
Stack stack=new Stack<>();
for(int i=0;iwhile(!stack.isEmpty()){
stringBuffer.append(stack.pop());
}
return stringBuffer.toString();
}
public static void main(String[] args) {
String str="I am a student.";
System.out.println(reverseStr(str));
}
}
查找字符串重复问题因为会用到哈希也常被放在面试中。
找出给定字符串中第一个不重复的字母。例如:abcccaddd,第一个不重复的字母是b。
public class FirstNotRepeatingChar {
public static char firstNotRepeatChar(String str){
// 256个字母
char temp=str.charAt(0);
int[] hashTimes=new int[256];
for(int i=0;ifor (int i=0;iif(hashTimes[str.charAt(i)]==1)
return str.charAt(i);
}
return '\77';
}
public static void main(String[] args) {
System.out.println(firstNotRepeatChar("aaaaaaaaaaaaaa"));
}
}
1.求1的阶乘到n的阶乘的和。
public class GetSumFactorial {
public static long getAddFactorial(long n){
if(n<=0) return -1;
long sum=0,start=1,end=n;
long mid;
while (start<=end){
sum+=getSingleFactorial(end);
end--;
}
return sum;
}
private static long getSingleFactorial(long i) {
if(i<1) return -1;
if(i==1) return 1;
return getSingleFactorial(i-1)*i;
}
public static void main(String[] args) {
System.out.println(getAddFactorial(4));
// 异常值 如果n比较大的时候,递归消耗内存就会导致程序启动报栈溢出异常,这个时候可以通过设置jvm的参数-Xss512k来解决这个问题 (如果主动考虑到这个 可以作为面试中的加分项哦) System.out.println(getAddFactorial(100000));
}
}
2.给一个有序排列的整数数组a[n],整数数组有且仅有一个值缺失,求当前缺失的值。例子 a[10]={0,1,2,3,5,6,7,8,9,10},返回缺失的值为4.
其中,方法一和方法二都是递归的思路,只不过方法一是用了二分法求和的递归思路,方法二是利用数组的特点进行递归,递归仍然使用二分的思想。
public class QueryLackedInt {
// 方法一:根据数组特性即可求出缺失的值
public static int getNum1(int[] data) {
if (data == null || data.length == 0) return -1;
if (data[0] != 0) return 0;
int len = data.length;
int sum1 = getSum(data, 0, len - 1);
int sum2 = (len + 1) * (data[0] + data[len - 1]) / 2;
return sum2 - sum1;
}
public static int getSum(int[] data, int low, int high) {
if (data == null || data.length == 0) return -1;
if (low == high) {
return data[low];
} else {
int mi = (low + high) >> 1;
return getSum(data, low, mi) + getSum(data, mi + 1, high);
}
}
// 方法二:使用两个指针进行递归
public static int getNum2(int[] data) {
if (data == null || data.length == 0) return -1;
if (data.length >= 1 && data[0] != 0) return 0;
return getRecursion(data, 0, data.length-1);
}
private static int getRecursion(int[] data, int left, int right) {
int mid = (left + right) / 2;
if (right == left && data[left] != left) return left;
if (data[mid] == mid) {
return getRecursion(data, mid+1, right);
} else {
return getRecursion(data, left, mid);
}
}
public static void main(String[] args) {
int[] a = {0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12,13, 14, 15};
int[] b = null;
int[] c = {1, 2};
System.out.println(getNum1(a));
System.out.println(getNum1(b));
System.out.println(getNum1(c));
System.out.println(getNum2(a));
System.out.println(getNum2(b));
System.out.println(getNum2(c));
}
}