剑指 Offer 03. 数组中重复的数字

如果没有重复数字,那么正常排序后,数字i应该在下标为i的位置,所以思路是重头扫描数组,遇到下标为i的数字如果不是i的话,(假设为m),那么我们就拿与下标m的数字交换。在交换过程中,如果有重复的数字发生,那么终止返回ture
class Solution {public int findRepeatNumber(int[] nums) {int len = nums.length;for(int i = 0; i < len;i++) {while(nums[i]!=i) {if(nums[nums[i]]==nums[i])return nums[i];else // 交换nums[i] 与 nums[nums[i]]swap(nums,nums[i],i);}}return -1;}void swap(int[] nums,int a,int b){int t = nums[a];nums[a] = nums[b];nums[b] = t;}}
51. N 皇后

class Solution {List<List<String>> res = new ArrayList();List<String> list = new ArrayList();public List<List<String>> solveNQueens(int n) {int[] len = new int[n];dfs(len,0);return res;}void dfs(int[] arr,int start){// 找到位置,转变成字符串if(start==arr.length){for(int c:arr) {char[] ch = new char[arr.length];Arrays.fill(ch,'.');int i = 0;while((c&(1<<i))==0) {i++;}ch[ch.length-i-1]='Q';list.add(new String(ch));}res.add(new ArrayList(list));list.clear();return;}// 当前行的棋盘分布int now = arr[start];// 依次实验该行所有的位置放置queenwhile(now<=(1<<(arr.length-1))){if(now==0) {now=1;arr[start] = 1;} else {arr[start] = now;}// 判断if(check(arr,start)) {dfs(arr,start+1);}now=now<<1;}// 一定不要忘了归位,比如[1,4,0,0]时候,第三行无解,此时[1,4,8,0],如果第三行不归零,下一次now直接变成了8,而不是0arr[start] = 0;}boolean check(int[] arr,int start) {// 检查列for(int i = start-1;i>=0;i--) {if((arr[start]&arr[i])!=0)return false;}// \斜对角线int now = arr[start]<<1;for(int i = start-1;i>=0;i--,now<<=1) {if((now&arr[i])!=0)return false;}// /斜对角线now = arr[start]>>1;for(int i = start-1;i>=0;i--,now>>=1) {if((now&arr[i])!=0)return false;}return true;}}
52. N皇后 II

class Solution {int res = 0;public int totalNQueens(int n) {int[] len = new int[n];dfs(len,0);return res;}void dfs(int[] arr,int start){if(start==arr.length){res++;return;}int now = arr[start];while(now<=(1<<(arr.length-1))){if(now==0) {now=1;arr[start] = 1;} else {arr[start] = now;}// 判断if(check(arr,start)) {dfs(arr,start+1);}now=now<<1;}// 一定不要忘了归位,比如[1,4,0,0]时候,第三行无解,此时[1,4,8,0],如果第三行不归零,下一次now直接变成了8,而不是0arr[start] = 0;}boolean check(int[] arr,int start) {// 检查列for(int i = start-1;i>=0;i--) {if((arr[start]&arr[i])!=0)return false;}int now = arr[start]<<1;for(int i = start-1;i>=0;i--,now<<=1) {if((now&arr[i])!=0)return false;}now = arr[start]>>1;for(int i = start-1;i>=0;i--,now>>=1) {if((now&arr[i])!=0)return false;}return true;}}
2. 两数相加

class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode dummy = new ListNode();ListNode pre = dummy;boolean f = false; // 进位while(l1!=null || l2!=null || f){int v1 = l1==null?0:l1.val; // 这样不必单独判断某个链表是不是空了int v2 = l2==null?0:l2.val;int v = v1+v2;if(f){v++;}if(v>=10){v-=10;f=true;} else {f = false;}pre.next = new ListNode(v);pre = pre.next;if(l1!=null){l1=l1.next;}if(l2!=null){l2=l2.next;}}return dummy.next;}}
445. 两数相加 II

用栈
- 然后依次出栈
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/class Solution {public ListNode addTwoNumbers(ListNode h1, ListNode h2) {Stack<ListNode> s1 = new Stack();Stack<ListNode> s2 = new Stack();ListNode l1 = h1;ListNode l2 = h2;while(l1!=null) {s1.push(l1);l1=l1.next;}while(l2!=null){s2.push(l2);l2 = l2.next;}ListNode dummy = new ListNode();boolean f = false;while(!s1.isEmpty() || !s2.isEmpty() || f) {int v1 = s1.isEmpty()?0:s1.pop().val;int v2 = s2.isEmpty()?0:s2.pop().val;int v = v1+v2;if(f){v+=1;}if(v>=10) {v-=10;f = true;} else {f = false;}ListNode p = new ListNode(v);p.next = dummy.next;dummy.next = p;}return dummy.next;}}
55. 跳跃游戏

 
- 然后依次出栈
 遍历数组,判断当前节点可以到达的最远距离,更新最远距离
class Solution {public boolean canJump(int[] nums) {if(nums.length==1)return true;int last = nums[0]; // 当前可以到达的最远距离if(last>=nums.length-1)return true;for(int i = 1; i < nums.length;i++) {if(last<i) { // 当前距离不可达return false;}last = Math.max(i+nums[i],last);if(last>=nums.length-1)return true;}return false;}}
45. 跳跃游戏 II

我们维护当前能够到达的最大下标位置,记为边界。我们从左到右遍历数组,到达边界时,更新边界并将跳跃次数增加 1。class Solution {public int jump(int[] nums) {int end = 0; // 上一次跳跃最后可以达到的位置int maxPos = 0; // 已经探索到的最大的位置int len = nums.length;if(len==1)return 0;int step = 0;for(int i = 0 ; i < len;i++) {maxPos = Math.max(maxPos,i+nums[i]);if(maxPos>=len-1) { // 从当前节点跳跃可以跳到最后位置及其以后的位置return step+1;}if(i==end) { // 已经到达了上一次探索的极限,需要加一步了step++;end = maxPos; // 这一步可以探索到的极限}}return step;}}
128. 最长连续序列

去重
遍历每个元素,找每个开头
class Solution {public int longestConsecutive(int[] nums) {Set<Integer> set = new HashSet();for(int i:nums){ // 去重set.add(i);}int longest = 0;for(int now:set) {// 如果没有比当前数字小一的数字,那它就是开头的数字if(!set.contains(now-1)) {int nowLong = 1;// 一次找比他大的数字while(set.contains(now+1)) {now++;nowLong++;}longest = Math.max(longest,nowLong);}}return longest;}}
347. 前 K 个高频元素

- 用hash记录每个元素出现的次数
 - 使用一个k大小的小顶堆
 遍历hash,如果大于堆顶,弹出,加入当前元素
class Solution {public int[] topKFrequent(int[] nums, int k) {Map<Integer,Integer> map = new HashMap();for(int num:nums){map.put(num,map.getOrDefault(num,0)+1);}PriorityQueue<int[]> set = new PriorityQueue(new Comparator<int[]>(){public int compare(int[] m,int[] n) {return m[1]-n[1];}});for (Map.Entry<Integer, Integer> entry : map.entrySet()) {if(set.size()<k) {set.add(new int[]{entry.getKey(),entry.getValue()});} else {if(set.peek()[1]<entry.getValue()) {set.poll();set.add(new int[]{entry.getKey(),entry.getValue()});}}}int[] ret = new int[k];for (int i = 0; i < k; ++i) {ret[i] = set.poll()[0];}return ret;}}
