JAVA实现 剑指offer第二版 2

面试题16:数值的整数次方

需要考虑底数为0的情况,指数为正或负的情况;在计算次方时,应注意到4次方为2次方的2次方,可以进行递归调用减少复杂度;也要主要到double类型的比较不能直接使用==;
private static boolean g_InvalidInput = false;
    public static void main(String[] args){
        System.out.print(Power(0,-1));
    }
    public static double Power(double base,int exponent){
        if (Double.doubleToLongBits(base) == Double.doubleToLongBits(0.0) && exponent <= 0){
            g_InvalidInput = true;
            return 0.0;
        }
        int absponent = exponent;
        if (exponent < 0){
            absponent = 0-exponent;
        }
        double result = PowerWithUnsignedExponent(base,absponent);
        if (exponent<0){
            return 1.0/result;
        }
        return result;
    }
    public static double PowerWithUnsignedExponent(double base,int absponent){
        if (absponent == 0){
            return 1;
        }else if (absponent == 1){
            return base;
        }

        double result = PowerWithUnsignedExponent(base,absponent>>1);
        result *= result;

        if ((absponent & 0x1) == 1){
            result *= base;
        }
        return result;
    }

面试题17_1:打印从1到最大的n位数

用字符串处理大数问题,每次对字符串形式的数模拟+1功能,边加边打
同字符串,递归构建,其实是0-9的n位全排列问题,递归地,从0位开始构建字符串,每当构建到最后1位,输出这个串;
    public static void TomaxofNDigits(int n){
        if (n<=0){
            return;
        }
        char[] temp = new char[n];
        for (int i = 0;i<=9;i++){
            temp[0] = (char)(i+'0');
            PrintToMaxOfNDigitsRecursively(temp,0);
        }
    }
    public static void PrintToMaxOfNDigitsRecursively(char[] temp,int index){
        if (index == temp.length-1){
//            System.out.println(String.valueOf(temp));
            PrintNumber(temp);
            return;
        }
        for (int x = 0;x<=9;x++){
            temp[index+1] = (char)(x+'0');
            PrintToMaxOfNDigitsRecursively(temp,index+1);
        }
    }
    public static void PrintNumber(char[] temp){

//        System.out.println(String.valueOf(temp));
        int num = 0;
        for(int x = 0;x<temp.length;x++){
            if ( temp[x] == '0'){
                num = x+1;
                continue;
            }
            break;
        }
//        System.out.println(num);
        if (num == temp.length){
            return;
        }

        for (int y = num;y<temp.length;y++){
            System.out.print(temp[y]);
        }
        System.out.print('\n');

    }

面试题17_2:大数相加

考虑两个数均为负数或均为正数的情况,以及一正一负的情况;
public static void main(String[] args){
        char[] st1 = {'-','9','2','3','4'};
        char[] st2 = {'+','1','8','2','6'};
        System.out.print(String.valueOf(add_bignum(st1, st2)));
    }
    //char[0]为符号位,0的符号位认定为+,st1和st2的位数相同,不足的补0
    public static char[] add_bignum(char[] st1,char[] st2){
        if (st1 == null || st2 == null || st1.length <=1 || st2.length <=0){
            return null;
        }
        if (st1[0] == st2[0]){
            char[] st_sum = new char[st1.length+1];
            st_sum[0] = st1[0];
            int takeover = 0;
            for (int i = st1.length -1;i>=1;i--){
                int nSum = st1[i]-'0'+(st2[i]-'0')+takeover;
//                System.out.println(nSum);
                if (nSum>9){
                    takeover = 1;
                    st_sum[i+1] = (char)(nSum - 10+'0');
                }else {
                    takeover = 0;
                    st_sum[i+1] = (char)(nSum+'0');
                }
//                System.out.println(st_sum[i+1]);

            }
            if (takeover == 1){
                st_sum[1] = '1';
            }
            return st_sum;
        }else {
            char[] st_sum = new char[st1.length];
            int jiewei = 0;
            for (int x = st1.length-1;x>=1;x--){
                int dec = 0;
                if (st1[0] == '+'){
                    dec = st1[x]-'0'-(st2[x]-'0')-jiewei;
                }else {
                    dec = st2[x]-'0'-(st1[x]-'0')-jiewei;
                }

                if (dec<0){
                    jiewei = 1;
                    if (x == 1){
                        st_sum[x] = (char)(0-dec+'0');
                    }else {
                        st_sum[x] = (char) (10 + dec + '0');
                    }
                }else {
                    jiewei = 0;
                    st_sum[x] = (char)(dec+'0');
                }
            }
            if (jiewei == 1){
                st_sum[0] = '-';
            }else {
                st_sum[0] = '+';
            }
            return st_sum;
        }

    }

面试题18_1:删除链表的节点

基于该节点在此链表中的假设;将x+1的值赋给x,再改动指针;对于尾节点只能顺序遍历;空指针或只有一个节点的链表需要单独处理;
 public static int delete(MyLinkList st ,MyLinkList.Node temp){
        if (st == null || temp == null){
            return -1;
        }
        if (temp == st.getRoot()){
            st = null;
            return 1;
        }
        if (temp.next == null){
            MyLinkList.Node cursor = st.getRoot();
            while (cursor.next != temp){
                cursor = cursor.next;
            }
            cursor.next = temp.next;
            st.print();
            return 1;
        }

        temp.data = temp.next.data;
        temp.next = temp.next.next;
        st.print();
        return 1;
    }

18_2:删除链表中重复的节点

元素是有序排列的,删除的是值相同的节点;就是遍历一遍即可,需要两个指针,一个记录前一个节点的信息;                                                  
    public static int deleteduplication(MyLinkList st){
        if (st == null){
            return -1;
        }
        MyLinkList.Node start = st.getRoot();
        MyLinkList.Node pre = null;
        while (start != null){
            if (start.next != null && start.next.data == start.data){
                int value = start.data;
                start = start.next;
                while (start.next != null && start.next.data == value){
                    start = start.next;
                }
                if (pre == null){
                    st.getRoot().next = start.next;
                }else {
                    pre.next = start.next;
                }
            }
            if (st.getRoot().next == start.next){
                pre = null;
            }else {
                pre = start;
            }
            start = start.next;

        }
        st.print();
        return 1;

    }

19:正则表达式匹配

模式中第二个字符不是*时,比较字符串中第一个字符和模式中第一个字符;第二个字符是*时,若匹配,则字符串向后移一位,不匹配则模式移动2位。
    public static boolean matchCore(char[] str,char[] pattern){
        if (str == null || pattern == null  || pattern.length == 0 ){
            return false;
        }

        int index1 = 0;
        int index2 = index1;

        for (;index1<pattern.length-1;index1++){
            if (index2 > str.length-1){
                return false;
            }
            if (pattern[index1+1] != '*'){
                if (pattern[index1] != str[index2] && pattern[index1] != '.'){
                    return false;
                }else {
                    index2++;
                }
            }
            else if (pattern[index1+1] != ' '){
                if (pattern[index1] == str[index2]){
                    index2 ++;
                    index1 --;
                    if (index2 == str.length-1){
                        index1++;
                        break;
                    }
                }else {
                    index1 ++;
                }
            }else {
                break;
            }
        }
        if (index1 < pattern.length -2){
            return true;
        }
        if (index2 <= str.length-1){
            return false;
        }else {
            return true;
        }

    }

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

以正负号,小数点,e或E为标志,分段判断字符串;(+- )A(.)A(E,e)(+-)(A)
    public static boolean isNumeric(){
        Scanner can = new Scanner(System.in);
        String st = can.nextLine();
//        String st = "12e";
        if (st == null || st.length() == 0){
            return false;
        }

        int index_dian = -1;
        int index_e = -1;
        char[] temp = st.toCharArray();
        for (int x = 0;x<temp.length;x++){
            if (temp[x] == '.'){
                index_dian = x;
                break;
            }
        }
        for (int x = 0;x<temp.length;x++){
            if (temp[x] == 'E' ||temp[x] == 'e'){
                index_e = x;
                break;
            }
        }
        if (index_dian == st.length()-1 || index_e == st.length()-1){
            return false;
        }
        if (index_dian == -1 && index_e == -1){
            return isSignedInterge(st);
        }else if (index_dian != -1 && index_e == -1){

            if (index_dian == 0){
                return isInterge(st.substring(1));
            }else {
                return (isSignedInterge(st.substring(0,index_dian)) || isInterge(st.substring(0,index_dian))) && isInterge(st.substring(index_dian+1));
            }

        }else if (index_dian == -1 && index_e != -1){

                return (isSignedInterge(st.substring(0,index_e)) || isInterge(st.substring(0,index_e))) && (isSignedInterge(st.substring(index_e+1)) || isInterge(st.substring(index_e+1)));
        }else {


            if (index_dian>=index_e){
                return false;
            }else {
                return (isSignedInterge(st.substring(0,index_dian)) || isInterge(st.substring(0,index_dian))) && (isInterge(st.substring(index_dian+1,index_e))) && (isSignedInterge(st.substring(0,index_e)) || isInterge(st.substring(0,index_e)));
            }
        }

    }
    public static boolean isSignedInterge(String temp){
        char[] s = temp.toCharArray();
        if (s.length < 0 ){
            return false;
        }
        if (s[0] != '+' && s[0] != '-'){
            return false;
        }
        return isInterge(temp.substring(1));
    }

    public static boolean isInterge(String temp){
        char[] s = temp.toCharArray();
        if (s.length < 0 ){
            return false;
        }
        for(char x : s){
            if ( x > '9' || x<'0'){
                return false;
            }
        }
        return true;
    }

面试题21:调整数组顺序使奇数位于偶数前面

设置两个指针,一个指针从头开始,扫描到不符合规则的时,移动第二个指针从尾开始找一个符合规则的,交替,直至指针相遇;
 public static int[] Reorder(int[] source){
        if (source == null || source.length == 0){
            return null;
        }
        if (source.length == 1){
            return source;
        }
        int index_1 = 0;
        int index_2 = source.length-1;

        while (index_1<index_2){
            if (isOdd(source[index_1]) != true){
                while (isOdd(source[index_2]) == false){
                    index_2--;
                }
                if (index_2<= index_1){
                    break;
                }
                int temp = source[index_1];
                source[index_1] = source[index_2];
                source[index_2] = temp;
                index_2 -- ;
            }
            index_1++;
        }

        return source;
    }
    public static boolean isOdd(int x){
        if (x%2 == 0){
            return false;
        }else {
            return true;
        }
    }

面试题22_1:链表倒数第k个节点

设置两个指针,一个指针先走k-1步,再一起走直至先走的指针到达链表尾
 public static Node FindthToTail(Node head,int k){
        if (head == null || k<=0){
            return null;
        }
        Node temp_1 = head;
        Node temp_2 = head;

        for (int x = 0;x<k-1;x++){
            if (temp_1.next != null){
                temp_1 = temp_1.next;
            }else {
                return null;
            }
        }
        while (temp_1.next!= null){
            temp_1 = temp_1.next;
            temp_2 = temp_2.next;
        }
        return temp_2;

    }

面试题22_2:求链表的中间节点

设置两个指针,一个指针走2步的同时一个指针移动一步,当第一个指针到达链表尾时,第二个指针到达中间节点;
 public static Node getMid(Node head){
        if (head == null){
            return null;
        }
        if (head.next == null){
            return head;
        }
        Node temp_1 = head;
        Node temp_2 = head;
        while (temp_1.next != null){
            temp_1 = temp_1.next;
            if (temp_1.next != null){
                temp_1 = temp_1.next;
            }else {
                break;
            }
            temp_2 = temp_2.next;
        }
        return temp_2;
    }

面试题23:链表中环的入口节点

通过设置两个指针,一个指针以2倍速行走,若追上慢速指针,则证明该链表中存在环;

环的入口节点可以通过,一个指针先走环中节点个数步,第二个指针再一起走,相遇的节点就是入口节点;

环中节点数可以通过判断是否存在环时,相遇节点,再次走到相遇节点则得到环的节点数;

 public static Node EntryNodeOfLoop(Node head){
        if (head == null || head.next == null){
            return null;
        }

        Node meet = IfLoop(head);
        if (meet == null){
            return null;
        }
        int num = count(meet);

        Node t1 = head;
        Node t2 = head;
        for (int x = 1;x<=num;x++){
            t1 = t1.next;
        }

        while (t1!=t2){
            t1 = t1.next;
            t2 = t2.next;
        }

        return t1;

    }
    public static Node IfLoop(Node head){
        Node s1 = head;
        Node s2 = head;

        while (s1.next!= null){
            s1 = s1.next;
            if (s1.next == null){
               break;
            }
            s1 = s1.next;
            s2 = s2.next;
            if (s2 == s1){
                return s1;
            }
        }
        return null;
    }
    public static int count(Node meet){
        int count = 0;
        Node temp = meet.next;
        while (temp!=meet){
            count++;
            temp = temp.next;
        }
        return count+1;
    }
面试题24:反转链表

记录当前节点,当前节点的前一个节点以及后一个节点,从到到尾遍历,并记录链表尾作为链表头;
递归处理;
public static Node ReverseList(Node head){
        if (head == null || head.next == null){
            return head;
        }
        Node pre = null;
        Node t1 = head;
        Node aft = null;

        while (t1.next != null){
            aft = t1.next;
            t1.next = pre;

            pre = t1;
            t1 = aft;
        }
        t1.next = pre;
        return t1;

    }
  public static Node ReverseList_re(Node head){
        if (head == null || head.next == null){
            return head;
        }
        Node newhead = ReverseList_re(head.next);
        head.next.next = head;
        head.next = null;
        return newhead;
    }

面试题25:合并两个排序的链表

比较头节点,然后递归的进行比较
public static Node combine(Node head1,Node head2){
        if (head1 == null){
            return head2;
        }
        if (head2 == null){
            return head1;
        }


        if (head1.value<head2.value){
            Node newhead = combine(head1.next,head2);
            head1.next = newhead;
            return head1;
        }else {
            Node newhead = combine(head1,head2.next);
            head2.next = newhead;
            return head2;
        }
    }

面试题26:树的子结构

查找与2树根节点相同的节点,若找到,则遍历检查其子树是否同b相同
public static boolean hasSubtree(Node head1,Node head2){
        if (head1 == null || head2 == null){
            return false;
        }

        boolean res = false;
        if (equal(head1.value,head2.value)){
            res = DoesTree1HaveTree2(head1,head2);
        }
        if (!res){
            res = hasSubtree(head1.left,head2);
        }
        if (!res){
            res = hasSubtree(head1.right,head2);
        }
        return res;
    }
    public static boolean DoesTree1HaveTree2(Node head1,Node head2){
        if (head2 == null){
            return true;
        }
        if (head1 == null){
            return false;
        }
        boolean res ;
        if (!equal(head1.value,head2.value)){
            return false;
        }

        res = DoesTree1HaveTree2(head1.left,head2.left);
        if (res){
            res = DoesTree1HaveTree2(head1.right,head2.right);
        }
        return res;

    }
    public static boolean equal(double d1 ,double d2){
        if ((d1 - d2>-0.00000001) && (d1-d2 < 0.000000001)){
            return true;
        }
        return false;
    }


 
 

猜你喜欢

转载自blog.csdn.net/u011010851/article/details/79996780
今日推荐