11. 二进制中1的个数
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
这道题没有想出来,参考了大神的解答,理解了:
先附上代码:
public class Solution {
public int NumberOf1(int n) {
int count = 0;
while(n!= 0){
count++;
n = n & (n - 1);
}
return count;
}
}
接下来附上大神的解答:
下面附上一个比较java的解法:
public class Solution {
public int NumberOf1(int n) {
int t=0;
char[]ch=Integer.toBinaryString(n).toCharArray();
for(int i=0;i<ch.length;i++){
if(ch[i]=='1'){
t++;
}
}
return t;
}
}
12. 数值的整数次方
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
这个题目考察的是程序的完备性,注意到有以下几种情况需要考虑:
1. 底为 0 的情况
这种情况下,还要分成
1. 0 的 0 次方等于 1(不过我在网上查的是无意义,所以初次编写的时候输出 -1 没有通过所有范例)
2. 0 的 正整数次方为 0
3. 0 的 负数次方为 无意义 输出-1
2. 底不为 0 的情况
这种情况下,还要分成
1. 指数 > 0, 正常计算
2. 指数 = 0, 输出 0
3. 指数 < 0, 输出值的倒数
代码如下:
public class Solution {
public double Power(double base, int exponent) {
if(base == 0){
if(exponent == 0)
return 1;
else if(exponent > 0)
return 0;
else
return -1;
}else {
if(exponent == 0)
return 1;
else if(exponent > 0)
return PosPower(base, exponent);
else
return 1 / PosPower(base, -exponent);
}
}
public double PosPower(double base, int exponent){
double result = base;
for(int i = 1; i < exponent; i++)
result *= base;
return result;
}
}
看到了牛客网上大神的代码,佩服佩服:
public class Solution {
public double Power(double base, int exponent) {
double result = base;
int n = exponent;
if (exponent < 0) {
exponent = - exponent;
}
else if(exponent == 0) {
return 1;
}
for (int i = 1; i < exponent; i++) {
result *= base;
}
return n < 0 ? 1 / result : result;
}
}
13. 调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
这个题目主要有两种思路,一种不开辟新空间,采用类似于冒泡算法的方式,使奇数依次冒泡到前面,时间复杂度会比较大。还有种方法是开辟新空间,换取一些时间。我先从前往后遍历 array,奇数放到前面,偶数放到临时栈,最后从后往前存储栈中偶数:
import java.util.Stack;
public class Solution {
public void reOrderArray(int [] array) {
Stack<Integer> stack = new Stack();
int index = 0;
int i = 0;
while(i < array.length) {
if(array[i] % 2 == 1) {
array[index] = array[i];
index++;
}else{
stack.push(array[i]);
}
i++;
}
i--;
while(!stack.isEmpty()) {
array[i] = stack.pop();
i--;
}
}
}
14. 链表中倒数第k个结点
输入一个链表,输出该链表中倒数第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(k <= 0 || head == null)
return null;
ListNode front = head;
ListNode back = head;
for(; k > 1; k--){
front = front.next;
if(front == null)
return null;
}
while(front.next != null) {
front = front.next;
back = back.next;
}
return back;
}
}
15. 反转链表
输入一个链表,反转链表后,输出链表的所有元素。
思路1:利用 stack 存储,然后重新赋值,时间复杂度是 O(n):
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
import java.util.*;
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head == null)
return null;
Stack<Integer> stack = new Stack();
ListNode tmp = head;
while(tmp != null){
stack.push(tmp.val);
tmp = tmp.next;
}
tmp = head;
while(tmp != null){
tmp.val = stack.pop();
System.out.println(tmp.val);
tmp = tmp.next;
}
return head;
}
}
思路2:改变指针方向,具体思路参考 【刷题笔记/剑指Offer】Part 1 (1-10) 中的题目二中的2解法:
/*
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;
else if(head.next == null)
return head;
ListNode index = head, right = head.next;
while(right != null) {
index.next = right.next;
right.next = head;
head = right;
right = index.next;
}
ListNode tmp = head;
while(tmp!=null){
System.out.println(tmp.val);
tmp = tmp.next;
}
return head;
}
}
思路3:其实本质上和思路二差不多的,只不过这里要用三个指针:
/*
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 newHead = null;
ListNode pNode = head;
ListNode pPrev = null;
while(pNode!=null){
ListNode pNext = pNode.next;
if(pNext==null)
newHead = pNode;
pNode.next = pPrev;
pPrev = pNode;
pNode = pNext;
}
return newHead;
}
}
16. 合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
本题目可以分为递归和非递归两种解法,需要注意的是我刚开始的思路是不破坏两个链表的结构,则需要新建空间,但是怎么也没法通过,原来牛客网是要不新建空间。下面附上非递归的解法:
/*
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;
else if(list2 == null)
return list1;
ListNode head = null;
if(list2.val < list1.val){
head = list2;
list2 = list2.next;
}
else{
head = list1;
list1 = list1.next;
}
ListNode list = head;
while(list1 != null && list2 != null) {
if(list2.val < list1.val) {
list.next = list2;
list2 = list2.next;
}else{
list.next = list1;
list1 = list1.next;
}
list = list.next;
}
if(list1 != null){
list.next = list1;
}
if(list2 != null){
list.next = list2;
}
return head;
}
}
接下来是递归解法:
/*
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;
else if(list2 == null)
return list1;
ListNode head;
if(list2.val < list1.val){
head = list2;
list2 = list2.next;
}else{
head = list1;
list1 = list1.next;
}
head.next = Merge(list1, list2);
return head;
}
}
17. 树的子结构
输入两颗二叉树A,B,判断B是不是A的子结构。
/**
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) {
if(root2 == null)
return false;
if(root1 == null)
return false;
boolean flag = false;
if(root1.val == root2.val) {
flag = isSubtree(root1, root2);
}
if(!flag){
flag = HasSubtree(root1.left, root2);
if(!flag)
flag = HasSubtree(root1.right, root2);
}
return flag;
}
public boolean isSubtree(TreeNode root1, TreeNode root2) {
if(root2 == null)
return true;
if(root1 == null && root2 != null)
return false;
if(root1.val == root2.val){
return isSubtree(root1.left, root2.left) && isSubtree(root1.right, root2.right);
}else
return false;
}
}
18. 二叉树的镜像
操作给定的二叉树,将其变换为源二叉树的镜像。
递归实现,so easy:
/**
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) {
if(root == null)
return;
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
Mirror(root.left);
Mirror(root.right);
return;
}
}
至于非递归方法,要借助栈实现,注意这里先压入左树还是右树没有关系,但是在遍历的时候就要注意先压入后遍历的子树,最后压入要先遍历的子树,代码如下:
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
import java.util.*;
public class Solution {
public void Mirror(TreeNode root) {
if(root == null)
return;
Stack<TreeNode> stack = new Stack();
stack.push(root);
while(!stack.isEmpty()) {
TreeNode tmp = stack.pop();
TreeNode swap = tmp.left;
tmp.left = tmp.right;
tmp.right = swap;
if(tmp.right!=null)
stack.push(tmp.right);
if(tmp.left!=null)
stack.push(tmp.left);
}
}
}
19. 顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵:1 2 3 45 6 7 89 10 11 1213 14 15 16则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
画出图后,有了大体的思路,每次遍历了最上面一行矩阵元素后,将剩下的矩阵逆时针转动90°当作新的矩阵,剩下的就是递归直到剩下的矩阵行或列为零。只是这个方法每次都要涉及到申请矩阵空间和矩阵复制,效率没有那么高。看了网上其他人的解答后,恍然大悟,可以将开始结束的范围作为形参传递到递归的下个子函数,这种方法在每次要缩小范围的问题里经常应用,要注意。下面先给出我自己的解答:
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printMatrix(int [][] matrix) {
ArrayList<Integer> list = new ArrayList<Integer>();
assistant(matrix, list);
return list;
}
public void assistant(int [][] matrix, ArrayList<Integer> list) {
if(matrix.length == 0 || matrix[0].length == 0)
return;
for(int i = 0; i < matrix[0].length; i++) {
list.add(matrix[0][i]);
}
int [][] tmp = new int[matrix[0].length][matrix.length - 1];
for(int i = 0; i < matrix.length - 1; i++) {
for(int j = 0; j < matrix[0].length; j++)
tmp[j][i] = matrix[i + 1][matrix[0].length - 1 - j];
}
assistant(tmp, list);
return;
}
}
接下来是将索引作为形参的方法:
import java.util.*;
public class Solution {
public ArrayList<Integer> printMatrix(int[][] matrix) {
ArrayList<Integer> result = new ArrayList<Integer>() ;
if(matrix==null || matrix.length==0) { return result ; }
printMatrixClockWisely(matrix, 0, 0, matrix.length - 1, matrix[0].length - 1, result);
return result ;
}
public void printMatrixClockWisely(int[][] matrix, int startRow, int startCol, int endRow, int endCol, ArrayList<Integer> result) {
if(startRow<endRow && startCol<endCol) {
for(int j=startCol; j<=endCol; j++) { result.add(matrix[startRow][j]) ; } //Right
for(int i=startRow+1; i<=endRow-1; i++) { result.add(matrix[i][endCol]) ; } //Down
for(int j=endCol; j>=startCol; j--) { result.add(matrix[endRow][j]) ; } //Left
for(int i=endRow-1; i>=startRow+1; i--) { result.add(matrix[i][startCol]) ; } //Up
printMatrixClockWisely(matrix, startRow + 1, startCol + 1, endRow - 1, endCol - 1, result) ;
}else if(startRow==endRow && startCol<endCol) {
for(int j=startCol; j<=endCol; j++) { result.add(matrix[startRow][j]) ; }
}else if(startRow<endRow && startCol==endCol) {
for(int i=startRow; i<=endRow; i++) { result.add(matrix[i][endCol]) ; }
}else if(startRow==endRow && startCol==endCol) {
result.add(matrix[startRow][startCol]) ;
}else {
return ;
}
}
}
20. 包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
我最开始的思路是用另一个栈作为辅助栈,存储stack中弹出的元素,在过程中就可以得出min,最后stack的结构不被破坏,当然这种方法比较费空间,看了一下其他人的答案,有用迭代器的,觉得这是个好办法,要好好借鉴一下,下面先附上我的代码:
import java.util.Stack;
public class Solution {
Stack<Integer> stack = new Stack<Integer>();
public void push(int node) {
stack.push(node);
}
public void pop() {
stack.pop();
}
public int top() {
return stack.peek();
}
public int min() {
Stack<Integer> tmp = new Stack<Integer>();
int min = top();
while(!stack.isEmpty()) {
if(top() < min)
min = top();
tmp.push(stack.pop());
}
while(!tmp.isEmpty())
push(tmp.pop());
return min;
}
}
然后是用迭代器的代码:
import java.util.Stack;
import java.util.Iterator;
public class Solution {
Stack<Integer> stack = new Stack<Integer>();
public void push(int node) {
stack.push(node);
}
public void pop() {
stack.pop();
}
public int top() {
return stack.peek();
}
public int min() {
int min = stack.peek();
int tmp = 0;
Iterator<Integer> iterator = stack.iterator();
while (iterator.hasNext()){
tmp = iterator.next();
if (min>tmp){
min = tmp;
}
}
return min;
}
}
当然了,还有的同志直接从轮子开始造起,想一想最基本的几个东西来组成一个栈结构,拿最普通的数组栈来说事儿的话:
1. int[] elements = new int[100]; //初始长度
2. void enLarge() //当存储元素到达上限时,扩大容量
3. int node //指向尾部的指针
这样最基本的几个变量已经够了,剩下就是push,pop,top,min等操作啦~