剑指offer(Java版)面试题47——57

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

面试题47:扑克牌顺子

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。

代码:
        import java.util.Arrays;
        public class Solution {
            public boolean isContinuous(int [] numbers) {
                if(numbers==null || numbers.length<=1) return false;
                int p=0;
                Arrays.sort(numbers);
                for(int i=0;i<numbers.length;i++) {
                    if(numbers[i] != 0) {
                        p = i;
                        break;
                    }
                }
                if(p==numbers.length-1) return true;
                int n = numbers[numbers.length-1] - numbers[p];
                if(n<=numbers.length-1 && n>0) {
                    return true;
                }else {
                    return false;
                }
            }
        }

这道题的主要考点应该是在边界情况的全面考虑!

面试题48:孩子们的游戏(圆圈中最后剩下的数)

每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数….这样下去….直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)

代码1:推导出的复杂公式的代码,不过代码确实简洁
            public class Solution {
                public int LastRemaining_Solution(int n, int m) {
                    if(n<1 || m<1) return -1;
                    int last = 0;
                    for(int i=2;i<=n;i++) {
                        last = (last+m)%i;
                    }
                    return last;
                }
            }

代码2:采用环形链表

面试题49:求1+2+3+…+n

求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

代码:大神代码:利用递归和短路与的特性
        public class Solution {
            public int Sum_Solution(int n) {
                int sum = n;
                boolean flag = (sum>0)&&((sum+=Sum_Solution(--n))>0);
                return sum;
            }
        }

面试题50:不用加减乘除做加法

写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

代码:
        public class Solution {
            public int Add(int num1,int num2) {
                if(num1==0) {
                    return num2;
                }else if(num1<0) {
                    for(int i=0;i>num1;i--) {
                        num2--;
                    }
                }else {
                    for(int i=0;i<num1;i++) {
                        num2++;
                    }
                }
                return num2;
            }
        }

面试题51:把字符串转换成整数

将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0

代码:(这段代码在牛客是通过的,但是没有考虑溢出的情况)

        public int StrToInt(String str)
            {
                if (str.equals("") || str.length() == 0)
                    return 0;
                char[] a = str.toCharArray();
                int fuhao = 0;
                if (a[0] == '-')
                    fuhao = 1;
                int sum = 0;
                for (int i = fuhao; i < a.length; i++)
                {
                    if (a[i] == '+')  //为啥是a[i]呢?
                        continue;
                    if (a[i] < 48 || a[i] > 57)
                        return 0;
                    sum = sum * 10 + a[i] - 48;
                }
                return fuhao == 0 ? sum : sum * -1;
            }

//这道题的判题标准有问题,而且至今不知道为啥是a[i]==’+’,为啥不是a[0]

知识点: 字符 0 的ASCII码为48,9的ascii码值为57

面试题52:数组中重复的数字

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

代码:使用哈希作为辅助空间
        import java.util.LinkedHashMap;
        public class Solution {
            // 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<2) return false;
                LinkedHashMap<Integer,Integer> h = new LinkedHashMap<Integer,Integer>();
                for(int i=0;i<numbers.length;i++) {
                    if(h.containsKey(numbers[i])) {
                        duplication[0]=numbers[i];
                        return true;
                    }else {
                        h.put(numbers[i], 1);
                    }
                }
                return false;
            }
        }

面试题53:构建乘积数组

给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]A[i-1]*A[i+1]…*A[n-1]。不能使用除法。

代码:
        public class Solution {
            public int[] multiply(int[] A) {
                if(A==null) return null;
                if(A.length<2) return null;
                int [] B = new int [A.length];
                int [] head = new int [A.length];//从前往后
                int [] tail = new int [A.length];//从后往前
                for(int i=0;i<A.length;i++) {
                    if(i==0) {
                        head[0]=0;
                        tail[A.length-1]=0;
                        continue;
                    }
                    if(i==1) {
                        head[1]=A[0];
                        tail[A.length-2]=A[A.length-1];
                        continue;
                    }
                    head[i]=head[i-1]*A[i-1];
                    tail[A.length-1-i]=tail[A.length-i]*A[A.length-i];
                }
                for(int i=0;i<B.length;i++) {
                    if(i==0) {
                        B[0]=tail[0];
                        continue;
                    }
                    if(i==B.length-1) {
                        B[i]=head[B.length-1];
                        continue;
                    }
                    B[i] = head[i]*tail[i];
                }
                return B;
            }
        }

面试题54:正则表达式匹配

请实现一个函数用来匹配包括’.’和’‘的正则表达式。模式中的字符’.’表示任意一个字符,而’‘表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串”aaa”与模式”a.a”和”ab*ac*a”匹配,但是与”aa.a”和”ab*a”均不匹配.

代码:这道题好容易写到脑仁疼。。。

面试题55:表示数值的字符串

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串”+100”,”5e2”,”-123”,”3.1416”和”-1E-16”都表示数值。 但是”12e”,”1a3.14”,”1.2.3”,”+-5”和”12e+4.3”都不是。

代码1:正则大法好!!!
        public class Solution {
            public boolean isNumeric(char[] str) {
                String string = String.valueOf(str);
                return string.matches("[\\+-]?[0-9]*(\\.[0-9]*)?([eE][\\+-]?[0-9]+)?");
            }
        }

代码2:这道题考察的还是对于字符串的编程问题,不过字符串的是真的不好写!

面试题56:字符流中第一个不重复的字符

请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符”go”时,第一个只出现一次的字符是”g”。当从该字符流中读出前六个字符“google”时,第一个只出现一次的字符是”l”。
输出描述:如果当前字符流没有存在出现一次的字符,返回#字符。

代码:使用哈希来进行存储,并且利用了java中LinkedHashMap的有序性

        import java.util.LinkedHashMap;
        import java.util.Map;
        //使用哈希来进行存储,并且利用了java中LinkedHashMap的有序性
        public class Solution {
            LinkedHashMap<Character,Integer> h = new LinkedHashMap<>();
            //Insert one char from stringstream
            public void Insert(char ch)
            {
                if(h.containsKey(ch)) {
                    if(h.get(ch) != -1) {
                        h.replace(ch, 1, -1);
                    }   
                }else {
                    h.put(ch, 1);
                }
            }
          //return the first appearence once char in current stringstream
            public char FirstAppearingOnce()
            {
                for(Map.Entry<Character,Integer> set :h.entrySet()) {
                    if(set.getValue()==1) {
                        return (char)set.getKey();
                    }
                }
                return '#';
            }
        }

面试题57:链表中环的入口结点

一个链表中包含环,请找出该链表的环的入口结点。

代码:
        public ListNode EntryNodeOfLoop(ListNode pHead)
            {
                if(pHead == null || pHead.next == null) return null;
                ListNode p1 = pHead;
                ListNode p2 = pHead;
                while (p2 != null) {
                    p2 = p2.next.next;
                    p1 = p1.next;
                    if(p1 == p2) break; //为什么把这个条件加进while中就过不去呢?
                }
                p2 = pHead;
                while (p2 != p1) {
                    p2 = p2.next;
                    p1 = p1.next;
                }
                return p1;
            }

注意:
这道题是经典题,分为三个步骤:

    1. 判断是否有环
    2. 计算环中有多少个节点
    3. 找到环入口


第二种方法:左神讲的

    先说个定理:两个指针一个fast、一个slow同时从一个链表的头部出发
    fast一次走2步,slow一次走一步,如果该链表有环,两个指针必然在环内相遇
    此时只需要把其中的一个指针重新指向链表头部,另一个不变(还在环内),
    这次两个指针一次走一步,相遇的地方就是入口节点。

猜你喜欢

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