题目来自牛客网
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
提到二进制首先想到的最基本的除二取余算法,但是这题没有这么简单,因为cpu执行乘除法的指令周期要长, 解决办法是位运算。位运算的指令周期较短。二进制位运算右移相当于除以2,左移相当于乘2。然后用将1与该二进制数进行与运算,即可统计出末位1的个数。但是要注意的一点是,负数的话左边第一位是1,对负数进行右移会进入死循,为了 解决这一问题可以改为左移,然后同时也将进行与运算的1左移。
方法一:
class Solution11_1{//方法1,右移,但是负数时会进入死循环
public int NumberOf1(int n) {
int count=0;
while(n!=0) {
if((n&1)==1) {
count++;
}
n=n<<1;
}
return count;
}
}
方法二;
class Solution11_2{//方法2,左移
public int NumberOf1(int n) {
int count=0;
int flag=1;
while(flag!=0) {
if((n&flag)==1) {
count++;
}
flag=flag<<1;
}
return count;
}
}
方法三:来源牛客网神回复
class Solution11_3{//方法3,比较有新意的解法,一个数减去1在和原来的数进行与运算,会把该数最右边的1变成0
public int NumberOf1(int n) {
int count=0;
while(n!=0) {
++count;
n=(n-1)&n;
}
return count;
}
}
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
方法一:分类讨论,1:base=0;2:exponent=1;3:exponent>=0;4:exponent<0;然后用快速幂
方法二:公式:
a^n={
a^(n/2)*a^(n/2) n为偶数;
a^((n-1)/2)*a^((n-1)/2)*a n为奇数;
}
方法一:分类讨论
class Solution_12_1{
public double Power(double base, int exponent) {
double res = 0;
if(equal(base,0.0)) {
return 0.0;
}
if(exponent==1) {
return base;
}
if(exponent>=0) {
res = Pow(base,exponent);
}
if(exponent<0) {
res = 1.0/Pow(base,-exponent);
}
return res;
}
boolean equal(double a,double b) {
final double acc = 0.000001;
if(((a-b)>0&&(a-b)<=acc)||((b-a)>=0&&(b-a)<=acc)){
return true;
}
else {
return false;
}
}
double Pow(double base,int exponent) {
double ans=1;
while(exponent!=0) {
if((exponent & 1)!=0) {
ans *= base;
}
base *= base;
exponent >>= 1;
}
return ans;
}
}
方法二:使用公式
class Solution_12_2{
public double Power(double base, int exponent) {
if(exponent == 0) {
return 1;
}
if(exponent == 1) {
return base;
}
double result = Power(base,exponent >> 1);
result *= result;
if((exponent & 1) == 1) {
result *=base;
}
return result;
}
}
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
方法一:快排思想,会改变奇数和奇数,偶数和偶数之间的相对位置
方法二:将传入的数组复制一份,然后依次遍历奇数和偶数插入原数组
方法一:
class Solution_13{//快排思想,顺序会改变
public void reOrderArray(int [] array) {
int len=array.length;
int start=0,end=len-1;
while(start
方法二:
class Solution13_2 {
public void reOrderArray(int [] array) {
int len=array.length;
int []a=new int [len];
for(int i=0;i
输入一个链表,输出该链表中倒数第k个结点。
方法一:双指针,即使用两个指针,第一个比第二个先走k步之后,然后两个指针一起走,当第一个指针达到终点的时候,第二个指针指向的就是倒数第k个节点
方法二:使用栈,先将链表入栈,然后出栈,倒数第k个出栈的就是要找的数
方法一:
class Solution14 {
public ListNode FindKthToTail(ListNode head,int k) {
if(head==null||k==0) {
return null;
}
int len=1;
ListNode p =head;
while(p!=null) {
if(p.next!=null) {
len++;
}
p=p.next;
}
if(k>len) {
return null;
}
ListNode pre=head;
for(int i=0;i
方法二:
class Solution14_2 {
public ListNode FindKthToTail(ListNode head,int k) {
Stack stack = new Stack();
if(head == null || k ==0 ){
return null;
}
int count=0;
while(head!=null){
stack.push(head);
head=head.next;
count++;
}
if(count
输入一个链表,反转链表后,输出新链表的表头。
使用双指针,这里要注意的一点是断链的过程,一定要先将head指向下一个节点在调整p2
class Solution15 {
public ListNode ReverseList(ListNode head) {
if(head==null) {
return null;
}
ListNode p1,p2;
p1=head;
if(p1.next==null) {
return p1;
}
head=head.next;
p1.next=null;
while(head!=null) {
p2=head;
head=head.next;//注意:一定要先将head指向下一个再调p2
p2.next=p1;
p1=p2;
}
return p1;
}
}
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
这里主要是比较大小,然后将符合条件的节点断开接入链表就可以,不过要注意的有一点,多使用判断能减少一些不必要的插入操作
class Solution16 {
public ListNode Merge(ListNode list1,ListNode list2) {
if(list1==null&&list2==null) {
return null;
}
if(list1==null&&list2!=null) {
return list2;
}
if(list1!=null&&list2==null) {
return list1;
}
ListNode p=null;
if(list1.val<=list2.val) {
p=list1;
list1=list1.next;
}else {
p=list2;
list2=list2.next;
}
ListNode q=p;
while(list1!=null||list2!=null) {
if(list1==null&&list2!=null) {
q.next=list2;
break;
}
if(list1!=null&&list2==null) {
q.next=list1;
break;
}
if(list1.val<=list2.val) {
q.next=list1;
q=q.next;
list1=list1.next;
}else {
q.next=list2;
q=q.next;
list2=list2.next;
}
}
return p;
}
}
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
任意顺序遍历即可
class Solution17 {
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
boolean flag = false;
if(root1!=null && root2!=null) {
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;
}
private static boolean IsSubtree(TreeNode root1, TreeNode root2) {
if(root2==null) {
return true;
}
if(root1==null) {
return false;
}
if(root1.val!=root2.val) {
return false;
}
return IsSubtree(root1.left, root2.left)&&IsSubtree(root1.right, root2.right);
}
}
操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:
二叉树的镜像定义:
源二叉树
8
/ \
6 10
/ \ / \
5 7 9 11
镜像二叉树
8
/ \
10 6
/ \ / \
11 9 7 5
任意顺序遍历即可
class Solution18{
public void Mirror(TreeNode root) {
if(root==null) {
return ;
}
if(root.left!=null||root.right!=null) {
TreeNode t= root.left;
root.left=root.right;
root.right=t;
}
if(root.left!=null) {
Mirror(root.left);
}
if(root.right!=null) {
Mirror(root.right);
}
}
}
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下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.
首先确定圈数 ,然后以左上角的点和右下角的点为基准,逐圈打印
class Solution19{
public ArrayList printMatrix(int [][] matrix) {
ArrayList list = new ArrayList();
int l1=matrix.length;
int l2=matrix[0].length;
int circle ;//确定圈数
if(l1==0) {
return list;
}
if(l1<=l2) {
if(l1%2==0) {
circle=l1/2;
}else {
circle=(l1/2)+1;
}
}else {
if(l2%2==0) {
circle=l2/2;
}else {
circle=(l2/2)+1;
}
}//确定圈数结束
int ux=0,uy=0,dx=l2,dy=l1;//u为左上角的点,d为右下角的点,x为横坐标,y为纵坐标
for(int i=0;i=ux&&uy!=dy;p--) {//第三圈,这里加个判断防止一行时重复打印
list.add(matrix[dy-1][p]);
}
dy--;
for(int q=dy-1;q>=uy&&ux!=dx;q--) {//第四圈,同上加判断防止重复打印
list.add(matrix[q][ux]);
}
ux++;
}
return list;
}
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
新建一个栈,栈顶记录最小值即可
class Solution20{
private Stack stack = new Stack();
private Stack min = new Stack();
public void push(int node) {
stack.push(node);
if (min.isEmpty()) {
min.push(node);
} else if (node <= min.peek()) {
min.push(node);
}
}
public void pop() {
int value=stack.pop();
if(value==(min.peek())) {
min.pop();
}
}
public int top() {
return stack.peek();
}
public int min() {
return min.peek();
}
}