剑指offer系列刷题
第11题起步
位运算常用操作
题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
看一下大神写的代码
public class Solution {
public int NumberOf1(int n) {
return Integer.toBinaryString(n).replaceAll("0","").length();
}
}
//负数的补码是反码 +1 , 而反码 = 原码取反
下面是我能想出来的代码
举个例子: -1的补码是:11111111,这里有8个1,直接数就是了,用无符号右移动,也就是移位一次变成
011111111,-> 00111111->…->0000000
而带符号右移,负数最高位会补1
举个例子 11111111 -> 11111111 ,注意,少了一个一,人家又补了一个1,这样就是死循环了,我试过了
public class Solution {
public int NumberOf1(int n) {
int count=0;
while(n!=0) {
count+= n&1;
n=n>>>1;
}
return count;
}
}
日常水题
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
保证base和exponent不同时为0
public class Solution {
public double Power(double base, int exponent) {
if(exponent==0) return 1;
double t = base;
int len = Math.abs(exponent);
for(int i=1;i<len;++i)
{
base*=t;
}
if(exponent<0)
base = 1/base;
return base;
}
}
题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
import java.util.ArrayList;
public class Solution {
public void reOrderArray(int [] array) {
if(array.length==1||array.length==0) return;
merge(array);
}
public void merge(int[] arr)
{
ArrayList<Integer> left = new ArrayList();
ArrayList<Integer> right = new ArrayList();
for(int i: arr)
{
if((i&1)==0)//偶数
{
right.add(i);
}else{
left.add(i);
}
}
int r = arr.length-1;
do{
arr[r--]=right.remove(right.size()-1);
}while(right.size()!=0);
do{
arr[r--]=left.remove(left.size()-1);
}while(left.size()!=0);
}
}
个人思路:这一题我第一想到的就是归并排序,又要稳,又要快,就是内存开销大。我看题解里有用冒泡排序的,这就不写了
这里顺便写一些自己用插入排序写的代码
import java.util.ArrayList;
public class Solution {
public void reOrderArray(int [] array) {
if(array.length==1||array.length==0) return;
handle(array);
}
public void handle(int[] arr)
{
for(int i=0,j;i<arr.length;++i)
{
if((arr[i]&1)==0) continue;//arr[i] 是奇数,并且前一位是偶数
int curNode = arr[i];
for( j=i;j>0&&(arr[j-1]&1)==0;)
{
arr[j--]=arr[j];
}
arr[j]=curNode;
}
}
}
插入排序,如果是接近有序的数组,那么时间复杂度可以接近 O(N),而且是稳定的排序,还是很有学习意义的
下一题
链表的倒数第k个节点
题目描述
输入一个链表,输出该链表中倒数第k个结点。
import java.util.Stack;
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if(head==null) return head;
Stack<ListNode> stack = new Stack();
int len=0;
while(head!=null)
{
stack.push(head);
head = head.next;
len++;
}
ListNode ans = null;
if(len<k) return ans;
while((k--)>0)
{
ans = stack.pop();
}
return ans;
}
}
下一题
翻转链表
题目描述
输入一个链表,反转链表后,输出新链表的表头。
这是必会的水题,不会也要会,看到这个题开始想到用栈,java超时了,看了别人的答案反而自己敲不出来。。。这个题我刷过不下10遍了,结果硬是忘了
import java.util.Stack;
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head==null) return head;
ListNode l = null;//l指向断开那节
ListNode r = null;//r指向即将断开那节
while(head!=null)
{
r = head.next;
head.next = l;
l = head;
head = r;
}
return l;
}
}
下一题
合并两个排序链表
题目描述
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
public class Solution {
public ListNode Merge(ListNode list1,ListNode list2) {
ListNode begin = null,end = null;
begin = new ListNode(0);
end = begin;
while(list1!=null&&list2!=null)
{
if(list1.val<=list2.val)
{
end.next = list1;
list1 = list1.next;
end = end.next;
}else{
end.next = list2;
list2 = list2.next;
end = end.next;
}
}
while(list1!=null)
{
end.next = list1;
list1 = list1.next;
end = end.next;
}
while(list2!=null)
{
end.next = list2;
list2 = list2.next;
end = end.next;
}
return begin.next;
}
}
个人保证:日更5道题,到大三就没时间了,先耍耍,都是水题,大佬别笑,我不是打Acm的。