1.括号的匹配,要求输出一个字符串,里面包含(){}[]<>,当字符串中括号是成对出现的时候,返回true,否则返回false
例如:{(<>{})}返回的是true,而{(})([])返回的是false
思路:利用栈的后进先出的思想
public static boolean isMatch(String input){
Stack<Character> stack=new Stack<Character>();
char temp;
int len=input.length();
//循环input
for(int i=0;i<len;i++){
temp=input.charAt(i);
if(temp=='(') stack.push(')');
if(temp=='{') stack.push('}');
if(temp=='[') stack.push(']');
if(temp=='<') stack.push('>');
if(temp==')'||temp=='}'||temp==']'||temp=='>'){
char tempok=stack.pop();
if(temp!=tempok) return false;
}
}
if(stack.isEmpty()==true) return true;
else return false;
}
注意:上面括号的匹配代码是有问题的,更新于20170727。因为当字符串是右括号开始的时候会出现java.util.EmptyStackException,很显然没有考虑这种情况的发生,修改下判断方式,代码如下:
public boolean isValid(String s) {
Stack<Character> stack=new Stack<Character>();
for(int i=0;i<s.length();i++){
char ch=s.charAt(i);
if(ch=='(') stack.push(')');
else if(ch=='{') stack.push('}');
else if(ch=='[') stack.push(']');
else if(stack.isEmpty() || stack.pop()!=ch)
return false;
}
if(stack.isEmpty()){
return true;
}else{
return false;
}
}
2.输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
解题思路:利用Collections 的sort方法重写Comparator使得list中的数按照要求排好序,然后拼接list中的元素即可。
public String PrintMinNumber(int[] numbers){
int n=numbers.length;
ArrayList<Integer> list=new ArrayList<Integer>();
for(int i=0;i<n;i++){
list.add(numbers[i]);
}
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
String s1=o1+""+o2;
String s2=o2+""+o1;
return s1.compareTo(s2);
}
});
String result="";
for(int i:list){
result +=i;
}
return result;
}
3.求出1~n的整数中1出现的次数.
解题思路:将整数转换成String类型,然后转换为char数组,计算char中1的个数即可,代码如下:
public static int numOfOne(int n){
int nums=0;
if(n==0) return 0;
while(n>0){
String str=String.valueOf(n);
char[] cha=str.toCharArray();
for (int j=0;j<cha.length;j++){
if(cha[j]=='1') nums++;
}
n--;
}
return nums;
}
4.输入一个链表,输出该链表中倒数第k个结点
解题思路:定义两个指针,p1和p2,p1先走k-1,然后p2开始走,当p1走到结尾为空时,p2就是要找的位置
/*链表
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
//判断是否为null链表或者k不合法
if(head==null||k<=0) return null;
ListNode p1=head;
ListNode p2=head;
ListNode p3=head;
int count=0;
while (p3 != null) {
count++;
p3 = p3.next;
}
//当k大于当前链表的长度,也是null
if(k>count) return null;
//p1先走k-1步
for(int i=1;i<k;i++){
if(p1!=null)
p1=p1.next;
}
然后p1,p2同时移动,直到p1为空
while(p1.next!=null){
p1=p1.next;
p2=p2.next;
}
return p2;
}
}
5.输入一个字符串,包括数字字母符号,可以为空。将该字符串转换为一个整数。要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
解题思路:
public int StrToInt(String str) {
if(str.length()==0||str.equals("")) return 0;
int result=0;
int symbol=0;
char[] chas=str.toCharArray();
if(chas[0]=='-'){
symbol=1;
}
for (int i=symbol;i<chas.length;i++){
if (chas[i]=='+') continue;
if (chas[i]<48||chas[i]>57) return 0;
result =result*10+(chas[i]-48);
}
if (symbol==1) result=result*(-1);
return result;
}
6.在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3
解题思路:将数组拼接成字符串,然后使用replaceAll关键字,如果替代后字符串的长度小于原长度-1,说明是重复数字放到duplication中,暂停循环。
// Parameters:
// numbers: an array of integers
// length: the length of array numbers
// duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
// Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
// 这里要特别注意~返回任意重复的一个,赋值duplication[0]
// Return value: true if the input is valid, and there are some duplications in the array number
// otherwise false
public boolean duplicate(int numbers[],int length,int [] duplication) {
if(numbers==null||numbers.length==0) return false;
String str="";
for(int i=0;i<length;i++){
str +=numbers[i];
}
for(int i=0;i<length;i++){
String cha=numbers[i]+"";
if(str.replaceAll(cha,"").length()<str.length()-1) {
duplication[0] = numbers[i];
break;
}
}
//注意:这里应该判断数组的第一个元素是否大于0
if (duplication[0]>=0){
return true;
}
return false;
}
7.寻找假币问题
解决问题:分治算法,然后递归解决
public int falsecoin(int coins[],int low,int high){//low high是索引
int i,sum1,sum2;
int re=0;
sum1=sum2=0;
if(low+1==high){//这里是边界条件,写递归的时候一定注意边界条件。
if(coins[low]<coins[high]){
re=low+1;
return re;
}else{
re=high+1;
return re;
}
}
if((high-low+1)%2==0){//n是偶数
for(i=low;i<=low+(high-low)/2;i++){
sum1=sum1 + coins[i];
}//前半段的和
for(i=low+(high-low)/2+1;i<=high;i++){
sum2=sum2 + coins[i];
}//后半段的和
if(sum1>sum2){//如果前半段和大于后半段和则递归继续求解
re=falsecoin(coins,low+(high-low)/2+1,high);
return re;
}else{
re=falsecoin(coins,low,low+(high-low)/2);
return re;
}
}else{//n是奇数
for(i=low;i<=low+(high-low)/2-1;i++){
sum1=sum1+coins[i];
}
for(i=low+(high-low)/2+1;i<=high;i++){
sum2=sum2+coins[i];
}
if(sum1>sum2){
re=falsecoin(coins,low+(high-low)/2+1,high);
return re;
}else if(sum1<sum2){
re=falsecoin(coins,low,low+(high-low)/2);
return re;
}else{
re=low+(high-low)/2+1;
return re;
}
}
}
8.反转单词顺序
问题描述:例如,“student. a am I”正确的句子应该是“I am a student.”
解题思路:先将整个字符串进行反转,通过reverse()方法,然后分割反转后字符串再进行单个单词反转。
public String ReverseSentence(String str){
if(str==null) return null;
if(str.trim().equals("")) return str;
String result="";
StringBuffer sb=new StringBuffer(str);
String sbok=sb.reverse().toString();
String[] strs=sbok.split(" ");
for(int i=0;i<strs.length;i++){
StringBuffer stra=new StringBuffer(strs[i]);
stra.reverse();
result=result+stra+" ";
}
return result.trim();
}
9.扑克牌顺子
问题描述:LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…..LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何。为了方便起见,你可以认为大小王是0。
解题思路:先按照数组中的数从小到大排列,然后统计0的个数,从非0开始循环搜索,当当前的数加上1再加上0的个数大于当前后一个数(表明中间缺的可以用0来补全),继续搜索,直到数组最后一位并且0的个数是大于等于0的。
public static boolean isContinuous(int [] numbers) {
if(numbers.length==0) return false;
Arrays.sort(numbers);//先排序从小到大
int zero=0;
int i=0;
for(;i<numbers.length && numbers[i]==0;i++){
zero++;//统计0的个数
}
//从非0索引开始搜索
for(;i<numbers.length-1 && zero>=0;i++){
if(numbers[i]==numbers[i+1]) return false;
//0的个数可以继续匹配
zero =zero-(numbers[i+1]-numbers[i]-1);
//代表多少个0被用
}else{
return false;
}
}
return true;
}
10.地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
解题思路:递归回溯
1.从(0,0)开始走,每成功走一步标记当前位置为true,然后从当前位置往四个方向探索,
返回1 + 4 个方向的探索值之和。
2.探索时,判断当前节点是否可达的标准为:
1)当前节点在矩阵内;
2)当前节点未被访问过;
3)当前节点满足limit限制。
public int movingCount(int threshold,int rows,int cols){
int flag[][]=new int[rows][cols];//记录是否已经走过
return helper(0,0,rows,cols,flag,threshold);
}
private int helper(int i,int j,int rows,int cols,int[][] flag,int threshold){
if(i<0||i>=rows||j<0||j>=cols) return 0;
if(numSum(i)+numSum(j)>threshold||flag[i][j]==1) return 0;
flag[i][j]=1;
return helper(i-1,j,rows,cols,flag,threshold)
+helper(i+1,j,rows,cols,flag,threshold)
+helper(i,j-1,rows,cols,flag,threshold)
+helper(i,j+1,rows,cols,flag,threshold)
+1;
}
private int numSum(int i){
int sum=0;
while(i!=0){
sum +=i%10;
i=i/10;
}
return sum;
}
11.输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字
例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
public ArrayList<Integer> printMatrix(int[][] matrix){
ArrayList<Integer> result=new ArrayList<Integer>();
if(matrix==null||matrix.length==0) return result;
printMatrixClockWisely(matrix, 0, 0, matrix.length-1, matrix[0].length-1, result);
return result;
}
public void printMatrixClockWisely(int[][] matrix,int startRow,int startCol,int endRow,int endCol,ArrayList<Integer> result){
if(startRow<endRow && startCol<endCol){
for(int j=startCol;j<=endCol;j++) result.add(matrix[startRow][j]);
for(int i=startRow+1;i<=endRow-1;i++) result.add(matrix[i][endCol]);
for(int j=endCol;j>=startCol;j--) result.add(matrix[endRow][j]);
for(int i=endRow-1;i>=startRow+1;i--) result.add(matrix[i][startCol]);
printMatrixClockWisely(matrix, startRow+1, startCol+1, endRow-1, endCol-1, result);
}else if(startRow==endRow && startCol<endCol){
for(int j=startCol;j<=endCol;j++) result.add(matrix[startRow][j]);
}else if(startRow<endRow && startCol==endCol){
for(int i=startRow;i<=endRow;i++) result.add(matrix[i][startCol]);
}else if(startRow==endRow && startCol==endCol){
result.add(matrix[startRow][startCol]);
}else {
return;
}
}
12.给定一个非负整型数组,每一位代表当前位置能够跳动的最长步数,判断是够能够抵达最后一位。
public boolean canJump(int[] nums){
if(nums==null||nums.length==0) return false;
int n=nums.length;
if(n==1) return true;
int max=0;
int i=0;
while(i <=max && i<n){
max=Math.max(max,nums[i]+i);
if(max >=n-1) return true;
i++;
}
return max >=n-1;
}