面试题14:数值的整数次方
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
代码:(有点乱,可以整理的更清晰)
public class Solution {
public double Power(double base, int exponent) {
if(exponent==0) return 1.0;//0的0次方按照1来算
if(base == 0.0) {
if(exponent>0) {
return 0.0;
}else {
throw new RuntimeException("分母不能为0"); //分母为0的时候,要抛异常!
}
}
double s = 1;
if(exponent>0){ //指数为正的时候
for(int i=0;i<exponent;i++) {
s = s*base;
}
}else { //指数为负的时候
for(int i=0;i<-exponent;i++) {
s = s/base;
}
}
return s;
}
}
需要注意的点:
(1)java中作为基本数据类型的浮点数只有float和double。double是8字节,64位。
(2)如果开发者需要精确保存一个浮点数,则可以考虑使用BigDecimal类。
(3)int整数需要考虑负数、0、整数!,底数也需要考虑是否为0.同时,幂的运算要考虑正负数计算是不同的!
面试题15:调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
代码:(另外开辟了数组用来空间换时间,可以减少算法的复杂度)
public class Solution {
public void reOrderArray(int [] array) {
if(array == null) return;
int n = array.length;
int [] a;
a = new int [n];
int odd=0;//用来记录奇数的个数
for(int i=0;i<n;i++) {
if(array[i]%2 != 0) {
odd+=1;
}
}
if(odd==0 || odd==n) return;
int first=0,second=odd;
for(int i=0;i<n;i++) {
if(array[i]%2==0) {
a[second]=array[i];
second++;
}else {
a[first]=array[i];
first++;
}
}
for(int i=0;i<n;i++) {
array[i] = a[i];
}
}
}
面试题16:链表中倒数第k个结点
输入一个链表,输出该链表中倒数第k个结点。
注意:
头结点的数据域可以不存储任何信息,头结点的指针域存储指向第一个结点的指针(即第一个元素结点的存储位置)
方法一:定义快指针和慢
方法二:先求长度再去计算位置
public ListNode FindKthToTail(ListNode head,int k) {
//这个head就是链表的第一个节点!!
if(head == null) return null;
ListNode p = head;
int num=0;
while(p != null) {
p = p.next;
num++;
}
p = head;
if(num<k) {
return null;
}else {
for(int i=0;i<num-k;i++) {
p = p.next;
}
return p;
}
}
注意:牛客上面给出的头结点就是链表的第一个节点,而不是常规意义上的头结点!!切记!不然代码会错!
面试题17:反转链表
输入一个链表,反转链表后,输出链表的所有元素。
代码:
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head == null) return null;
//if(head.next==null) return head;
ListNode former = null;
ListNode latter = null;
while(head != null) {
former = head.next;
head.next = latter;
latter = head;
head = former;
}
return latter;
}
}
面试题18:合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
代码:(非递归版本)
public class Solution {
public ListNode Merge(ListNode list1,ListNode list2) {
if(list1 == null) return list2;
if(list2 == null) return list1;
ListNode head,current;
if(list1.val<list2.val) {
head = list1;
list1 = list1.next;
}else {
head = list2;
list2 = list2.next;
}
current = head;
while(list1 != null && list2 != null) {
if(list1.val < list2.val) {
current.next = list1;
list1 = list1.next;
}else {
current.next = list2;
list2 = list2.next;
}
current = current.next;
}
if(list1 != null) {
current.next=list1;
}else {
current.next = list2;
}
return head;
}
}
代码:(递归版本)
注意:两个链表的合并可以新建一个第三方链表来存储,这样减少了工作量!
面试题19:树的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
面试题20:二叉树的镜像
操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:
二叉树的镜像定义:源二叉树
8
/ \
6 10
/ \ / \
5 7 9 11
镜像二叉树
8
/ \
10 6
/ \ / \
11 9 7 5
代码:
public class Solution {
public void Mirror(TreeNode root) {
if(root == null) return;
TreeNode m = null;
m = root.left;
root.left = root.right;
root.right = m;
Mirror(root.left);
Mirror(root.right);
return;
}
}
注意:
这到期主要考察的就是二叉树的知识
面试题21:顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
代码:
面试题22:包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
代码:
import java.util.Stack;
public class Solution {
Stack<Integer> s1 = new Stack<Integer>();
Stack<Integer> s2 = new Stack<Integer>();
public void push(int node) {
s1.push(node);
if(s2.isEmpty()) {
s2.push(node);
}else if(s2.peek()<=node) {
s2.push(s2.peek());
}else {
s2.push(node);
}
}
public void pop() {
s1.pop();
s2.pop();//同步弹出
}
public int top() {
return s1.peek();
}
public int min() {
return s2.peek();
}
}
注意:
public peek() 查看栈顶对象而不移除它
2.使用的思路是用辅助栈来同步保存最小值!
面试题23:栈的压入、弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
代码1:(以push为外循环)
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
if(pushA.length==0 || popA.length==0) return false;
Stack<Integer> s = new Stack<Integer> ();
int i = 0;
for(int a : pushA) {
s.push(a);
while(!s.isEmpty() && s.peek()==popA[i] ) {
s.pop();
i++;
}
}
return s.isEmpty()?true:false;
}
}
代码二:(以pop为外循环)
思路:(这道题需要找规律)
借助辅助栈,如果当前的栈顶是要出栈的元素,那么直接弹出,如果不是,那么将后续需要入栈的元素压入,知道找到出栈元素,如果全都压入了还没找到,那么说明序列不可能是弹出序列!
这道题如果不借助辅助栈的话可能会非常麻烦,而借助辅助栈的话可以同步模拟压入的过程,查看是否是序列,这样问题就好解决了!
面试题24:从上往下打印二叉树
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
代码: import java.util.ArrayList; public class Solution { public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) { ArrayList<Integer> a=new ArrayList<Integer>(); ArrayList<TreeNode> list=new ArrayList<TreeNode>(); if(root==null) return a; list.add(root); while(list.size() != 0) { //注意:这里写list!=null是错的,因为list是存在的,只不过大小是0而已! TreeNode p = list.remove(0); a.add(p.val); if(p.left != null) { list.add(p.left); } if(p.right != null) { list.add(p.right); } } return a; } }
思路:不要把这种遍历看成是层与层之间的,而要看成是一个连着的!借助队列来实现
注意:
<1>队列:使用的也是ArrayList来模拟队列的实现,这个和Stack貌似不太一样。
<2>注意上面注释那里,这是小点可能会疏忽!
<3>这道题考察的是树和树的遍历算法,但是没有用到递归,而是结合了队列的数据结构,所以当问题超出常理的时候要尽量去思考能否用别的思维来解释,以及灵活结合其他的数据结构,比如:队列、栈、哈希表等!