一、写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
先看看十进制数的运算,比如6和7 不计进位得到3,计算进位得到10. 10+3 即为结果。
- 两个数异或:相当于每一位相加,而不考虑进位;
- 两个数相与,并左移一位:相当于求得进位;
- 上述两步的结果相加
6--->110 7---->111
110^111为001 即1
(110&111)<<1为12
1+12=13即为结果
public int Add(int num1,int num2) {
while( num2!=0 ){
int sum = num1 ^ num2;
int carray = (num1 & num2) << 1;
num1 = sum;
num2 = carray;
}
return num1;
}
二、找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
输入: [2, 3, 1, 0, 2, 5, 3] 输出:2 或 3
法1
class Solution {
public int findRepeatNumber(int[] nums) {
Set<Integer> set= new HashSet<Integer>();
int res=-1;
for(int num:nums)
if(!set.add(num)){ //add失败返回fasle 即找到了重复元素
res=num;
break;
}
return res;
}
}
解题方法利用了hashet集合中没有重复的值的特点。遍历nums,将元素添加到hashset中,直到某次失败,则说明找到了重复的数
法二
巧妙利用数组下标来匹配对应的元素,从前往后遍历数组,每个元素都要求下标与元素的值一一对应,如果在调换位置的过程中发现该位置的元素与别的位置的元素是相同的,那么就说明该数字重复,直接返回该数字
class Solution {
public int findRepeatNumber(int[] nums){
for (int i = 0; i < nums.length; i++){
//将数字与下标对应起来
while (nums[i] != i){
int temp = nums[i];
//如果准备移动的数字已经等于对应位置上的数字则说明数字重复
if(temp == nums[temp]) return temp;
nums[i] = nums[temp];
nums[temp] = temp;
}
}
return Integer.MAX_VALUE;
}
}
例如arr=[2,3,1,0,2,5,3]
当i=0,因arr[i]!=i,令temp=arr[i],此时temp为2。接着判断temp==arr[temp],2不等于1
所以交换。arr[i]=arr[temp],arr[temp]=temp
此时arr为[1,3,2,0,2,5,3]
当i=1,因arr[i]!=i,令temp=arr[i],此时temp为3。接着判断temp==arr[temp],3不等于0
所以交换。arr[i]=arr[temp],arr[temp]=temp
此时arr为[1,0,2,3,2,5,3]
当i=2,因arr[i]!=i, 2==2 while循环结束
当i=3,因arr[i]!=i, 3==3 while循环结束
当i=4,因arr[i]!=i,即2!=4,令temp=arr[i],此时temp为2。接着判断temp==arr[temp],2==2
所以return 2;
此时说明2重复了,程序结束
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。
给定一个链表: 1->2->3->4->5, 和 k = 2. 返回链表 4->5.
经典双指针,快指针先走k步,接着快慢指针一起每次走一步,直到快指针后继为空,此时慢指针所指的元素为导数第k个
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode q=head,s=head;
for(int i=0;i<k;i++){q=q.next;}
while(q!=null){
q=q.next;
s=s.next;
}
return s;
}
}
四、删除链表的节点
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if(head.val == val) return head.next;
ListNode pre = head, cur = head.next;
while(cur != null && cur.val != val) {
pre = cur;
cur = cur.next;
}
if(cur != null) pre.next = cur.next;
return head;
}
}