《剑指offer》Java实现(11-20)
11.给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
保证base和exponent不同时为0
public class Solution {
public double Power(double base, int exponent) {
double result=0;
/**
* base为0.0时
*/
if(equal(base,0.0)){
return 0.0;
}
if(equal(base,1.0)||equal(exponent,0.0)){
return 1.0;
}
if(exponent>0){
result=multiply(base,exponent);
}else{
result=multiply(1/base,-exponent);
}
return result;
}
//定义指数函数 x^n
private static double multiply(double x,double n){
double sum=1;
for(int i=0;i<n;i++){
sum*=x;
}
return sum;
}
//定义相等函数equal()
private static boolean equal(double a,double b){
if(a-b<0.000001&&a-b>-0.000001){
return true;
}
return false;
}
}
12.输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
public class Solution {
public void reOrderArray(int [] array) {
if(array==null||array.length==0){
return;
}
//计算奇数的个数
int oddNum=0;
for(int i=0;i<array.length;i++)
{
if(array[i]%2==1)
{
oddNum++;
}
}
//复制一个数组,如果要直接在原来的数组上操作没有办法赋值,很混乱,无法实现
int [] copy=array.clone();
//将数组分为两个部分,一部分存储奇数,一部分存储偶数
//奇数从oddflag开始存储
//偶数从evenflag开始存储
int oddflag=0;
int evenflag=oddNum;
for(int j=0;j<copy.length;j++)
{
if(copy[j]%2==1)
{
array[oddflag]=copy[j];
oddflag++;
}else
{
array[evenflag]=copy[j];
evenflag++;
}
}
}
}
13.输入一个链表,输出该链表中倒数第k个结点。
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
//快慢指针
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if(head==null||k<=0){
return null;
}
ListNode fast=head;
ListNode slow=head;
while(k-->1){
if(fast.next!=null){
fast=fast.next;
}else{
return null;
}
}
while(fast.next!=null){
fast=fast.next;
slow=slow.next;
}
return slow;
}
}
还有一个思路:就是把链表的所有元素压入栈中,然后出栈。这时,栈中出栈的元素顺序正好是链表中倒数第几个元素。但是时间复杂度较大,不建议。
14.输入一个链表,反转链表后,输出新链表的表头。
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode ReverseList(ListNode head) {
//压入栈中
if(head==null){
return null;
}
ListNode t=null;
//一直交换元素,直到t和最后一个元素交换,此时即为反转链表的头
while(head!=null){
//定义p来缓存
ListNode p=head.next;
head.next=t;
t=head;
head=p;
}
return t;
}
}
15.输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode Merge(ListNode list1,ListNode list2) {
//当其中一个链表为空,直接返回另一个就是结果
if(list1==null){
return list2;
}
if(list2==null){
return list1;
}
//定义新链表的头
ListNode newHead=null;
//递归 保证有序
if(list1.val<=list2.val){
newHead=list1;
newHead.next=Merge(list1.next,list2);
}else{
newHead=list2;
newHead.next=Merge(list1,list2.next);
}
return newHead;
}
}
16.输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
//递归 比较他们的子树是否相等
//如果根节点相等,继续递归比较他们的左子树的右子树
boolean result = false;
//如果为空
if (root1 == null||root2 == null){
return false;
}
//如果不为空 继续判断
if(root1 != null && root2 != null){
//该二叉树不是左小右大的
if(root1.val==root2.val){
result=isEqual(root1,root2);
}
if(!result){
result=isEqual(root1.left,root2);
}
if(!result){
result=isEqual(root1.right,root2);
}
}
return result;
}
public boolean isEqual(TreeNode root1,TreeNode root2){
//子树已经判断完毕了则结束,表明整个过程都为true,最终返回true
if(root2 == null){
return true;
}
//子树还没空,父树先走到空了,那么肯定是不是子树结构的
if(root1 == null) {
return false;
}
//值不相等
if(root1.val != root2.val){
return false;
}
return isEqual(root1.left,root2.left)&& isEqual(root1.right,root2.right);
}
}
17.操作给定的二叉树,将其变换为源二叉树的镜像。
import java.util.*;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public void Mirror(TreeNode root) {
while(root==null){
return;
}
Stack<TreeNode> stack=new Stack<>();
while(root!=null||!stack.isEmpty()){
while(root!=null){
//交换位置
TreeNode temp=root.left;
root.left=root.right;
root.right=temp;
stack.push(root);//压栈
root=root.left;//下一次递归
}
if(!stack.isEmpty()){
root=stack.pop();
root=root.right;
}
}
}
}
18.输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 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.
private static void printMatrixInCircle(int[][] numbers,int rows,int colums,int start){
int endX = colums-1-start;
int endY = rows-1-start;
/**从左向右打印一行*/
for(int i=start;i<=endX;i++){
int number=numbers[start][i];
System.out.print(number+" ");
}
/**从上到下打印一列*/
if(start<endY){
for(int i=start+1;i<=endY;i++){
int number = numbers[i][endX];
System.out.print(number+" ");
}
}
/**从右向左打印一行*/
if(start<endX && start<endY){
for(int i=endX-1;i>=start;i--){
int number = numbers[endY][i];
System.out.print(number+" ");
}
}
/**从下到上打印一列*/
if(start<endX && start<endY-1){
for(int i=endY-1;i>=start;i--){
int number = numbers[i][start];
System.out.print(number+" ");
}
}
}
public static void printMatrixClockwisely(int[][] numbers,int rows,int colums){
if(numbers==null || colums<0 || rows<0)
return;
int start=0;
while(colums>start*2 && rows>start*2){
printMatrixInCircle(numbers,rows,colums,start);
++start;
}
System.out.println();
}
19.定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
注意:保证测试中不会当栈为空的时候,对栈调用pop()或者min()或者top()方法。
import java.util.Stack;
//定义两个栈,一个存放入的值,另一个存最小值
//peek()函数返回栈顶的元素,但不弹出该栈顶元素。
//pop()函数返回栈顶的元素,并且将该栈顶元素出栈。
public class Solution {
Stack<Integer> stack1=new Stack<>();
Stack<Integer> stack2=new Stack<>();
public void push(int node) {
stack1.push(node);
if(stack2.isEmpty()){
stack2.push(node);
}else{
if(stack2.peek()>node){
stack2.push(node);
}
}
}
public void pop() {
if(stack1.pop()==stack2.peek()){
stack2.pop();
}
}
//返回栈顶元素
public int top() {
return stack2.peek();
}
public int min() {
return stack2.peek();
}
}
20.输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
import java.util.ArrayList;
import java.util.*;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
//为空的情况
if(pushA==null||popA==null){
return false;
}
Stack<Integer> stackData=new Stack<>();
//j代表pushA数组下标,i代表popA数组下标
int j=0,i=0;
stackData.push(pushA[j]);
while(j<pushA.length){
//popA中元素全部比较完成,说明此数组序列是pushA
if(i==popA.length){
return true;
}
//仅仅判断stackData为empty,不能说明此数组序列是pushA所对应的删除序列
if(i!=popA.length && stackData.isEmpty()||stackData.peek()!=popA[i]){
++j;
if(j<pushA.length)
stackData.push(pushA[j]);
}else if(stackData.peek()==popA[i]){
i++;
stackData.pop();
}
}
return false;
}
}
本人才疏学浅,如有错误,烦请指出,谢谢!