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