剑指offer(Java版)面试题36——46

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Katrina_ALi/article/details/81192933

面试题36:第一个只出现一次的字符位置

在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置

代码:(借助哈希)
        import java.util.LinkedHashMap;
        public class Solution {
            public int FirstNotRepeatingChar(String str) {
                LinkedHashMap <Character, Integer> map = new LinkedHashMap<Character, Integer>();
                for(int i=0;i<str.length();i++) {
                    if(map.containsKey(str.charAt(i))) {
                        int num = map.get(str.charAt(i));
                        num = num+10000;
                        map.put(str.charAt(i), num);
                    }else {
                        map.put(str.charAt(i), i);
                    }
                }
                int pos=-1;
                for(int i=0;i<str.length();i++) {
                    if(map.get(str.charAt(i))<10000) {
                        if(pos==-1) {
                            pos=i;
                        }else {
                            pos = Math.min(pos, i);
                        }
                    }
                }
                return pos;
            }
        }

面试题37:数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:

题目保证输入的数组中没有的相同的数字

数据范围:

对于%50的数据,size<=10^4

对于%75的数据,size<=10^5

对于%100的数据,size<=2*10^5

示例1
输入

1,2,3,4,5,6,7,0

输出

7

代码1:(牛客超时)
            public int InversePairs(int [] array) {
                    if(array == null) return 0;
                    int count=0;
                    for(int i=0;i<array.length-1;i++) {
                        for(int j=i+1;j<array.length;j++) {
                            if(array[i]>array[j]) count++;
                        }
                    }
                    int r = count%1000000007;
                    return r;
                }

代码2:

面试题38:两个链表的第一个公共结点

输入两个链表,找出它们的第一个公共结点。

代码:
        import java.util.Stack;
        public class Solution {
            public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
             if(pHead1==null || pHead2==null) return null;
                 //借助栈或者哈希都可以
                 Stack<ListNode> s1 = new Stack<ListNode>();
                 Stack<ListNode> s2 = new Stack<ListNode>();
                 ListNode p1 = pHead1;
                 ListNode p2 = pHead2;
                 while(p1 != null || p2 != null) {
                     if(p1 != null) {
                         s1.push(p1);
                         p1 = p1.next;
                     }
                     if(p2 != null) {
                         s2.push(p2);
                         p2 = p2.next;
                    } 
                 }
                 p1=null;
                 while(!s1.isEmpty() && !s2.isEmpty()) {
                     if(s1.peek() == s2.peek()){
                        p1 = s1.peek();
                         s1.pop();
                         s2.pop(); 
                     }else{
                         break;
                     }
                 }
                 return p1;
            }
        }

面试题39:数字在排序数组中出现的次数

统计一个数字在排序数组中出现的次数。

代码1:简单的从前到后的遍历
        public class Solution {
            public int GetNumberOfK(int [] array , int k) {
               if(array==null) return 0;
                int count=0;
                int flag=0;
                for(int i=0;i<array.length;i++) {
                    if(array[i] == k ) {
                        flag=1;
                        count++;
                    }else if(flag==1){
                        break;
                    }
                }
                return count;
            }
        }

代码2:融合二分查找法

面试题40:二叉树的深度

输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

代码:
        public class Solution {
            public int TreeDepth(TreeNode root) {
                if(root ==null) return 0;
                int num=0;
                num = digui(root,num);//当时调试的时候是这里出的问题
                return num;
            }
            public int digui(TreeNode root,int num) {
                if(root==null) return num;
                num = num+1;
                int num1 = digui(root.left,num);//注意num的值传递
                int num2 = digui(root.right,num);
                num = num1>num2? num1:num2;
                return num;
            }
        }

注意:这道题错的位置在加注释的地方,这道题本身不难,但是关于递归的思想和java函数的值传递的本质要有更深刻的认识!!!

面试题41:平衡二叉树

输入一棵二叉树,判断该二叉树是否是平衡二叉树。

代码:
        public class Solution {
            public boolean IsBalanced_Solution(TreeNode root) {
                if(root==null) return true;
                return getDepth(root)!=-1;
            }
            public int getDepth(TreeNode root) {
                if(root==null) return 0;
                int left = getDepth(root.left);
                if(left==-1) return -1;
                int right = getDepth(root.right);
                if(right==-1) return -1;
                if(left-right>=-1 && left-right<=1) {
                    return 1+Math.max(left, right) ;             
                }else {
                    return -1;      
                }
            }
        }

知识点:
1. 平衡二叉树:如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树

面试题42:数组中只出现一次的数字

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

代码1:HashMap
            //num1,num2分别为长度为1的数组。传出参数
            //将num1[0],num2[0]设置为返回结果
            import java.util.LinkedHashMap;
            import java.util.Set;
            public class Solution {
                public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
                    if(array==null) return;
                    LinkedHashMap<Integer,Integer> h = new LinkedHashMap<>();
                    for(int i=0;i<array.length;i++) {
                        if(h.containsKey(array[i])) {
                            h.remove(array[i],1);
                        }else {
                            h.put(array[i], 1);
                        }
                    }
                    int [] num ;
                    num = new int[2];
                    Set<Integer> s = h.keySet();
                    int j=0;
                    for(int i:s) {
                        num[j++]=i;
                    }
                    num1[0]=num[0];
                    num2[0]=num[1];
                }
            }

代码2:异或

面试题43:和为S的连续正数序列

>
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:

输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序.

代码:
            import java.util.ArrayList;
            public class Solution {
                public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
                    ArrayList<ArrayList<Integer> > a = new ArrayList<ArrayList<Integer> >(); 
                    if(sum<=2) return a;
                    int small=1,big=2;

                    int temp = big+small;
                    while(small<=sum/2) {
                        while(temp<sum) {
                            big+=1;
                            temp+=big;
                        }
                        if(temp==sum) {
                            ArrayList<Integer> t = new ArrayList<Integer>();
                            for(int i=small;i<=big;i++) {
                                t.add(i);
                            }
                            a.add(t);
                        }
                        temp-=small;
                        small+=1;
                    }
                    return a;
                }
            }

面试题44:和为S的两个数字

>
输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。(也就是最先找到的)
输出描述:

对应每个测试案例,输出两个数,小的先输出。

代码:
        import java.util.ArrayList;
        public class Solution {
            public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
                ArrayList<Integer> a = new ArrayList<Integer>();
                if (array == null || array.length < 2) {
                    return a;
                }
                int i=0,j=array.length-1;
                while(i<j){
                    if(array[i]+array[j]==sum){
                    a.add(array[i]);
                    a.add(array[j]);
                        return a;
                   }else if(array[i]+array[j]>sum){
                        j--;
                    }else{
                        i++;
                    }

                }
                return a;
            }
        }

注意:使用的是夹逼准则

面试题45:左旋转字符串

汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!

代码:
        public class Solution {
            public String LeftRotateString(String str,int n) {
                if(str==null || str.length()==0) return str;
                if(n<=0) return str;
                int length = str.length();
                String s,s1,s2;
                if(n<length) {
                    s1 = str.substring(0, n);//注意:substring(,)后面的索引是不包括的,所以这里是n而不是n-1
                    s2 = str.substring(n);
                    s = s2.concat(s1);
                }else if(n>length) {
                    int num = n%length;
                    s1 = str.substring(0, num);
                    s2 = str.substring(num);
                    s = s2.concat(s1);
                }else {
                    s = str;
                }
                return s;
            }
        }

面试题46:翻转单词顺序列

牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?

代码1:(未通过)但是我感觉方法是可以的
            public class Question46 {
                 public String ReverseSentence(String str) {
                     if(str==null || str.length()==0) return str;
                     String [] a;
                     int num=0;//计算空格的个数
                     for(int i=0;i<str.length();i++) {
                         if(str.charAt(i)==' ') {
                             num++;
                         }
                     }
                     if(num<1) return str;//处理单个单词的情况

                     a = new String[num+1];
                     int i1=0,j1=str.length()-1;
                     int i2=0,j2=str.length()-1;
                     int n = 0;
                         while(i2<=j2) {
                             if(str.charAt(i2)==' ' && str.charAt(j2)==' ') {
                                 a[n]=str.substring(j2+1, j1);//2动1不动
                                 a[a.length-1-n] = str.substring(i1, i2);
                                 n++;
                                 i2+=1;j2-=1;
                                 i1=i2;j1=j2;
                                 continue;
                             }
                             i2++;
                             j2--;   
                         }
                     if(num%2==0) {
                         a[a.length/2] = str.substring(i1, j1+1); //处理奇数的情况
                     }
                     String s =a[0];
                     for(int i=1;i<a.length;i++) {
                         s.concat(" ");
                         s.concat(a[i]);
                     }
                     return s;
                 }
            }

代码2:
            import java.util.Arrays;
            public class Solution {
                public String ReverseSentence(String str) {
                     if(str==null || str.length()==0) return str;
                     char [] a;
                     a = str.toCharArray();
                     int length=a.length;
                     //将整个字符串翻转
                     reverse(a,0,length-1);
                     //将单个单词内部进行翻转
                     int p1 = -1;
                     for(int p2=0;p2<length;p2++) {
                         if(a[p2]==' ') {
                            reverse(a,p1+1,p2-1); 
                            p1=p2;
                         }
                     }
                     reverse(a,p1+1,length-1);
                      return new String(a);
                }
                public void reverse(char [] a,int p1,int p2) {
                     while(p1<p2) {
                         char temp=a[p1];
                         a[p1] = a[p2];
                         a[p2] = temp;
                         p1++;
                         p2--;
                     }
                 }
            }

注意:关于字符串和字符数组之间的转化有很多捷径,所以不需要一直自己循环!

猜你喜欢

转载自blog.csdn.net/Katrina_ALi/article/details/81192933