Algorithm-a classic sql problem and a Java algorithm problem

1.sql title description

Say there is a log table with only two columns, which are consecutive id and num. As for what it means, treat it as an amount. Now I want to know the num of 3 consecutive times or more. The data is as follows

id on one
1 1
2 1
3 1
4 2
5 3
6 4
7 4
8 4

Then the result is only 1, 4 meet the conditions, ask how to write this SQL?

2. Ideas and solutions

Analysis: The title is simple, there is no ambiguity, and can be understood. For problems like several consecutive times, the window function must be used. The first thing that comes to mind is the ranking row_numberand laghow to reflect the continuity. It must be a sorted id. The title gives the id is continuously increasing, row_number can be omitted

So the first step, go to lag, the result is as follows:

id on one lagid
1 1 null
2 1 0
3 1 0
4 2 1
5 3 1
6 4 1
7 4 0
8 4 0

After getting the lagid, how to use it continuously? First, only 0 meets the condition, so you can do a filter, and the result is removed as shown in the table xxxbelow. Observe the 0 row below, how to distinguish the 0 in the 3 rows and the 0 in the 7 rows? Thinking of using a new grouping, rid will sort the same lagid and the same num, and add another column at the end, and group the same id-rid into a group

id on one lagid rid guide
1 1 null xxx
2 1 0 1 1
3 1 0 2 1
4 2 1 xxx
5 3 1 xxx
6 4 1 xxx
7 4 0 1 6
8 4 0 2 6
-- 完整sql
## 解法1
SELECT num
FROM
  (SELECT id,
          num,
          lagid,
          (id-row_number() over(PARTITION BY num, lagid
                                ORDER BY id)) AS gid
   FROM
     (SELECT id,
             num,
             num- lag(num) (OVER PARTITION BY 1
                            ORDER BY id) AS lagid) tmp1
   WHERE lagid=0 ) tmp2
GROUP BY num,
         gid
HAVING count(*) >= 2


## 解法2  
select
  num,
  gid,
  count(1) as c
from
(
select
id,
num,
id-row_number() over(PARTITION BY num ORDER BY id) as gid
from 
(select * from logs order by num,id) a
) b
group by num,gid

Later, I thought of a better one. In fact lag, there is no need , and there is no need for order byglobal sorting. The role of id is the same as date. It is generally used to cooperate row_numberto solve continuous problems, so it is row_numberessential. Then you can write it like this (God damn simple, is it? Don't think about it complicated):

SELECT num,
       gid
FROM
  (SELECT num,
          id-row_number() OVER (PARTITION BY num
                                ORDER BY id) gid
   FROM logs)
GROUP BY num,
         gid
HAVING count(1) >= 3
 

3. Java problem description

First, give you an initial array arr. Then, every day you have to generate a new array based on the previous day's array. The array generated on the i day is obtained by performing the following operations on the array on the i-1 day: If an element is smaller than its left and right neighbors, the element is incremented by 1. If an element is larger than its left and right neighbors, then the element is decremented by 1.

The first and last elements never change.

After some time, you will find that the array will no longer change. Please return to the final array.

Example 1:

Input: [6,2,3,4]

Output: [6,3,3,4]

Explanation:

On the first day, the array changed from [6,2,3,4] to [6,3,3,4].

No more operations can be performed on this array.

Example 2:

Input: [1,6,3,4,3,5]

Output: [1,4,4,4,4,5]

Explanation:

On the first day, the array changed from [1,6,3,4,3,5] to [1,5,4,3,4,5].

The next day, the array changed from [1,5,4,3,4,5] to [1,4,4,4,4,5].

No more operations can be performed on this array.

3.3 Analysis and solution

  1. First consider how to write a round of traversal. It should be very simple. The idea is to have a window of size 3.

  2. Use a flag to mark whether the data has been changed in each round. Then the code is as follows:

public int[] get(int[] input) {
    if (input == null || input.length <=2)
        return input;
    boolean flag = false;
        do {
            flag = false;
            for (int i=1;i+1 < input.length;i++){
                if (input[i] < input[i+1] && input[i] < input[i-1] ) {
                    input[i] +=1;
                    if (!flag)
                        flag = true;
                }
                if (input[i] > input[i+1] && input[i] > input[i-1] ) {
                    input[i] -=1;
                    if (!flag)
                        flag = true;
                    }
            }
        } while(flag)
        return input;
}

Wu Xie, Xiao San Ye, a little rookie in the background, big data, and artificial intelligence.
Please pay attention to more
file

Guess you like

Origin blog.csdn.net/hu_lichao/article/details/110456499