【leetcode】Weekly Contest 91

  leetcode周赛,早上起来发现没网,用热点意识模糊的a了三个水题。

1.Lemonade Change

  简单模拟题,收到十元用五元钱找回,收到20元时优先用一张10一张5,如果10不够用3张5,如果没有就返回flase(贪心)。

 1     public boolean lemonadeChange(int[] bills) {
 2         int five = 0;
 3         int ten = 0;
 4         int twenty = 0;
 5         for (int i = 0; i < bills.length; i++) {
 6             if (bills[i] == 5) {
 7                 five++;
 8             } else if (bills[i] == 10) {
 9                 if (five > 0) {
10                     five--;
11                     ten++;
12                 } else {
13                     return false;
14                 }
15             } else if (bills[i] == 20) {
16                 if (ten > 0 && five > 0) {
17                     five--;
18                     ten--;
19                     twenty++;
20                 } else if (five >= 3) {
21                     five -= 3;
22                     twenty++;
23                 } else {
24                     return false;
25                 }
26             }
27         }
28         return true;
29     }

2.All Nodes Distance K in Binary Tree

  找到target的位置,根据左(0)右(1)记录路径,再遍历(我用的是先根)一遍整颗树,每个点与target的距离是其“两点的深度和”减去“公共前缀的两倍”,判断是否与K相等即可。

 1     public List<Integer> distanceK(TreeNode root, TreeNode target, int K) {
 2         String t = findTarget(root,target,new String());
 3         return helper(root, K,t, new LinkedList<>(), new String());
 4     }
 5     public List<Integer> helper(TreeNode root,int k,String target,List<Integer> res,String s){//先根遍历
 6         if(root!=null){
 7             if(disK(target, s.toString(), k)){
 8                 res.add(root.val);
 9             }
10             helper(root.left, k, target, res, s+"0");
11             helper(root.right, k, target, res, s+"1");
12         }
13         return res;
14     }
15     public boolean disK(String s1,String s2,int k){//计算距离,距离=点1的深度+点2的深度-2倍的公共前缀深度
16         if(s1.length()>s2.length()){
17             String s = s1;
18             s1 = s2;
19             s2 = s;
20         }
21         int i;
22         for(i = 0;i<s1.length();i++){
23             if(s1.charAt(i) != s2.charAt(i)){
24                 break;
25             }
26         }
27         int dis = s1.length() + s2.length() - i*2;
28         return dis == k;
29     }
30     public String findTarget(TreeNode root, TreeNode target,String res){//查找target节点,返回路径
31         if(root == null){
32             return "w";
33         }
34         if(root == target){
35             return res;
36         }
37         String s = findTarget(root.left, target, res+"0");
38         if(s.equals("w")){
39             return findTarget(root.right, target, res+"1");
40         }else {
41             return s;
42         }
43     }

3.Score After Flipping Matrix

  在一行中,每一列中的值比后面所有的列和都要大,因此把第一列的值置为1是第一目标,所以首先转换行用于把第一列的值全置为1,第二列到最后一列只需要根据每一列的1的个数是否大于行数的一半,如果大于就翻转列,反之则该列已经最大。

 1     public int matrixScore(int[][] A) {
 2         int score = 0;
 3         for (int i = 0; i < A.length; i++) {//把第一列的所有值都用行转换变为1
 4             if (A[i][0] == 0) {
 5                 swap(A, true, i);
 6             }
 7             score += Math.pow(2, A[i].length - 1);
 8         }
 9         for (int j = 1; j < A[0].length; j++) {
10             int count = 0;//每一列1的个数
11             for (int i = 0; i < A.length; i++) {
12                 if (A[i][j] == 1) {
13                     count++;
14                 }
15             }
16             count = Math.max(count, A.length - count);//如果小于一半,就反转
17             score += Math.pow(2, A[0].length - 1 - j) * count;
18         }
19         return score;
20     }
21
22     public void swap(int[][] A, boolean row, int num) {//用于转换行、列(后来发现转换列其实不需要,只需要计算每列的个数,如果反转就把个数反转即可,因为该列是否反转与后序无关联)
23         if (row) {
24             for (int i = 0; i < A[0].length; i++) {
25                 A[num][i] ^= 1;
26             }
27         }
28     }

4.Shortest Subarray with Sum at Least K

  感觉A.length<=50000是最大的难点,当时没做出来,补题学到了一种很厉害的思路。首先用P[i]数组记录数组中第0个元素到第i个元素的和,因此P[y]-p[x]就是从位置x到y的和。

  然后,用一个双端队列,扫描一遍p数组,使队列保持递增(因为对于i<j,p[i]>p[j],则最小的距离肯定不是后面某个位置的值到i的和,而是到j的和,因此需要保持队列递增)。

  扫描每个点(比如i)的时候,用i与队列中首位的值配对,如果到队列首位位置的和比K大,则可以把队列首位的值remove掉,因为对于j>i来说,后面的所有符合条件的位置离队列首位记录的位置更远。

  可能听描述有点抽象,看代码就好啦!

 1     public int shortestSubarray(int[] A, int K) {
 2         int[] P = new int[A.length + 1];
 3         int res = Integer.MAX_VALUE;
 4         for (int i = 0; i < A.length; i++) {
 5             P[i + 1] = P[i] + A[i];
 6         }
 7         Deque<Integer> deque = new LinkedList<>();// 下面保证单调递增队列
 8         for (int i = 0; i < A.length + 1; i++) {
 9             while (!deque.isEmpty() && P[i] <= P[deque.getLast()]) {// 如果x1<y2
10                                                                     // 且p[y2]<p[x1]则把x1抛弃
11                 deque.removeLast();
12             }
13             while (!deque.isEmpty() && P[i] >= P[deque.getFirst()] + K) {// 从前找满足的位置
14                 res = Math.min(res, i - deque.removeFirst());// 如果满足就把队列中的那个点去掉,因为i之后的点-队列中的点位置肯定比当前点大
15             }
16             deque.addLast(i);
17         }
18         return res == Integer.MAX_VALUE ? -1 : res;
19     }

  oN的时间复杂度和空间复杂度,正好利用了区间和大于k这个条件(我才不会说我一开始看错题在思考怎么判断等于k)。很妙!

原文地址:https://www.cnblogs.com/zzzdp/p/9251907.html

时间: 2024-09-29 23:27:53

【leetcode】Weekly Contest 91的相关文章

【leetcode】Weekly Contest 94

题目不难,被第二题卡了半个多小时QAQ,另一个就是以后能用Hashmap和Hashset的绝不遍历. 1. Leaf-Similar Trees dfs.层次遍历把叶子节点遍历然后对比即可,只要是先遍历左节点后遍历右节点就行. 1 class Solution { 2 public boolean leafSimilar(TreeNode root1, TreeNode root2) { 3 ArrayList<Integer> res1 = new ArrayList<>();

【LeetCode】Minimum Depth of Binary Tree 二叉树的最小深度 java

[LeetCode]Minimum Depth of Binary Tree Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. 递归和非递归,此提比较简单.广度优先遍历即可.关键之处就在于如何保持访问深度. 下面是4种代码: 1

【LeetCode】字符串 string(共112题)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } [3]Longest Substring Without Repeating Characters [5]Longest Palindromic Substring [6]ZigZag Conversion [8]String to Integer (atoi) [10]Regular Expression Matching [12]Integer to Roman

【leetcode】557. Reverse Words in a String III

Algorithm [leetcode]557. Reverse Words in a String III https://leetcode.com/problems/reverse-words-in-a-string-iii/ 1)problem Given a string, you need to reverse the order of characters in each word within a sentence while still preserving whitespace

【leetcode】Generate Parentheses

题目: 给定整数n,返回n对匹配的小括号字符串数组. For example, given n = 3, a solution set is: "((()))", "(()())", "(())()", "()(())", "()()()" 分析: 这种问题的模式是:1)问题的解有多个 ,2)每个解都是由多个有效的 "步骤" 组成的,3)变更以有解的某个或某些"步骤"

【LeetCode】Implement strStr()

Implement strStr() Implement strStr(). Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack. 标准KMP算法.可参考下文. http://blog.csdn.net/yaochunnian/article/details/7059486 核心思想在于求出模式串前缀与后缀中重复部分,将重复信息保存在n

【LeetCode】Add Two Numbers

You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. Input: (2 -> 4 -> 3) + (5 -> 6 ->

【LeetCode】Pascal&#39;s Triangle

Pascal's Triangle Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,Return [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] 这题别想用通项公式做,n choose m里面的连乘必然溢出,老老实实逐层用定义做. class Solution { public: vector<vector<

【LeetCode】Copy List with Random Pointer

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null. Return a deep copy of the list. 思路:第一遍正常复制链表,同时用哈希表保存链表中原始节点和新节点的对应关系,第二遍遍历链表的时候,再复制随机域. 这是一种典型的空间换时间的做法,n个节点,需要大小为O(n