面试题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; }