LeetCode 725. Separate linked list / 326. 3 power / Sword finger Offer 62. The last remaining number in the circle (Joseph Ring problem)

Posted by jurdygeorge on Thu, 23 Sep 2021 15:01:05 +0200

725. Separate linked list

One question per day on September 22, 2021

Title Description

Given a linked list whose head node is root, write a function to separate the linked list into k consecutive parts.

The length of each part should be as equal as possible: the length difference between any two parts cannot exceed 1, that is, some parts may be null.

These k parts should be output in the order they appear in the linked list, and the length of the front part should be greater than or equal to the length of the back part.

Returns a list of linked lists that meet the above rules.

Example: 1 - > 2 - > 3 - > 4, k = 5 / / 5 result [[1], [2], [3], [4], null]

Example 1:

Input:
root = [1, 2, 3], k = 5
Output: [[1], [2], [3], [], []]
Explanation:
Each part of the input and output should be a linked list, not an array.
For example, the entered node root val= 1, root.next.val = 2, \root.next.next.val = 3, and root.next.next.next = null.
The first output[0] is output[0].val = 1, output[0].next = null.
The last element output[4] is null, which represents that the last part is an empty linked list.

Example 2:

Input:
root = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], k = 3
Output: [1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
Explanation:
The input is divided into several consecutive parts, and the length difference of each part is no more than 1. The length of the front part is greater than or equal to the length of the rear part.

Tips:

Length range of root: [0, 1000]
Size range of each node entered: [0, 999]
Value range of k: [1, 50]

Source: LeetCode
Link: https://leetcode-cn.com/problems/split-linked-list-in-parts
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

thinking

It's not a simple simulation
The idea is very simple, but the code is still difficult to implement

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode[] splitListToParts(ListNode head, int k) {
        ListNode node = head;
        int l = 0;

        while(node != null){
            l++;
            node = node.next;
        }

        int t = l / k;
        int remain = l % k;
    
        node = head;
        ListNode[] res = new ListNode[k];
        int tt = t;
        
        int idx = 0;
        while(idx < k){
            res[idx] = node;

            while(tt-- > 0 && node != null){
                node = node.next;
            }

            if(remain > 0){
                node = node.next;
                remain--;
            }
            tt = t;
            idx++;
        }
        idx = 1;
        node = head;
        while(idx < k && node != null){
            if(node.next == res[idx]){
                node.next = null;
                node = res[idx];
                idx++;
            }
            else
                node = node.next;
        }
        return res;
    }
}

I don't know how to write it separately after one traversal
Learn how to write once

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode[] splitListToParts(ListNode head, int k) {
        int l = 0;
        ListNode node = head;
        while(node != null){
            node = node.next;
            l++;
        }
        int t = l / k;
        int remain = l % k;
        node = head;
        ListNode[] res = new ListNode[k];
        int idx = 0;
        while(idx < k && node != null){
            res[idx] = node;
            //Because you want to reach the previous node of the next starting node
            int step = t + (remain-- > 0 ? 1 : 0);
            while(step-- > 1){
                node = node.next;
            }
            
            ListNode cur = node.next;
            node.next = null;
            node = cur;
            idx++;
        }
        return res;
    }
}

326. Power of 3

One question per day on September 23, 2021

Title Description

Given an integer, write a function to determine whether it is a power of 3. If yes, return true; Otherwise, false is returned.

The integer n is to the power of 3, which needs to be satisfied: there is an integer x so that n == 3x

Example 1:

Input: n = 27
Output: true

Example 2:

Input: n = 0
Output: false

Example 3:

Input: n = 9
Output: true

Example 4:

Input: n = 45
Output: false

Tips:

-2^31 <= n <= 2^31 - 1

Advanced:

Can you complete the problem without using loops or recursion?

Source: LeetCode
Link: https://leetcode-cn.com/problems/power-of-three
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

thinking

First of all, the most conventional idea is to divide by 3 all the time. If the remainder is not 0, it is not the power of 3; If there is one left, it is

class Solution {
    public boolean isPowerOfThree(int n) {
        while(n != 0 && n % 3 == 0){
            n /= 3;
        }
        return n == 1;
    }
}

Then type the watch,

class Solution {
    static Set<Integer> set = new HashSet<>();
    static{
        int i = 1;
        set.add(i);
        while(i <= Integer.MAX_VALUE / 3){
            i *= 3;
            set.add(i);
        }
    }
    public boolean isPowerOfThree(int n) {
        return n > 0 && set.contains(n);
    }
}

Then note that I just started to write a table like this, and then reported a memory overflow error. After thinking about it, i*3 must be out of range

class Solution {
    static Set<Integer> set = new HashSet<>();
    static{
        int i = 1;
        set.add(i);
        //error code 
        while(i * 3 <= Integer.MAX_VALUE){
            i *= 3;
            set.add(i);
        }
    }
    public boolean isPowerOfThree(int n) {
        return n > 0 && set.contains(n);
    }
}

Because 3 is a prime number, the power and factor of 3 are also the power of 3, so here we directly take the power of the largest 3 in the Integer range, and then take the remainder of n

public class Solution {
    //Knowing the limit of n, we can now infer that the maximum value of n, that is, the power of 3, is 116261467.
    //Since 3 is a prime number, the factor of the maximum value can only be a power of 3. Therefore, if the maximum value is divided by n and the remainder is 0, the power of 3 is obtained
    public boolean isPowerOfThree(int n) {
        return n > 0 && 1162261467 % n == 0;
    }
}

Next, use the toString() method to convert n into a ternary number
Then judge whether the ternary number is 10000... In this form, judge with the regular expression, and forget the regular expression here, but it will disappear at a glance

public class Solution {
    public boolean isPowerOfThree(int n) {
        //The first method is used to convert the number n to a base of 3 and return it in the form of string;
        //The second method is used to check whether there is a specific string in the string,
        //This regular expression is used to check whether the string starts with 1, followed by 0 or more zeros, and does not contain any other values$
        return Integer.toString(n, 3).matches("^10*$");
    }
}

The next method is also mathematics
Because n = 3^x, find X and judge whether x is an integer, that is, find the logarithm of log based on 3 bits and n
Then, because there are logarithms based on 10 in java, use the formula to convert it

public class Solution {
    //This method is pure mathematical calculation, that is, I = log3 (n); In Java, there is a logarithm with the lower value of 10, so the formula becomes:
    //log10(n)/log10(3) to judge whether the result is an integer 
    public boolean isPowerOfThree(int n) {
        return (Math.log10(n) / Math.log10(3)) % 1 == 0;
    }
}

Sword finger Offer 62. The last remaining number in the circle

Title Description

The N numbers 0,1, ···, n-1 are arranged in a circle, starting from the number 0, and the m-th number is deleted from the circle each time (counting from the next number after deletion). Find the last number left in the circle.

For example, the five numbers 0, 1, 2, 3 and 4 form a circle. Starting from the number 0, delete the third number each time, then the first four deleted numbers are 2, 0, 4 and 1 in turn, so the last remaining number is 3.

Example 1:

Input: n = 5, m = 3
Output: 3

Example 2:

Input: n = 10, m = 17
Output: 2

Limitations:

1 <= n <= 10^5
1 <= m <= 10^6

Source: LeetCode
Link: https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

thinking

I met some problems in the written examination today. Let's review it
First, very intuitive simulation, very slow:

class Solution {
    public int lastRemaining(int n, int m) {
        List<Integer> list = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            list.add(i);
        }
        int idx = 0;
        while (n > 1) {
            idx = (idx + m - 1) % n;
            list.remove(idx);
            n--;
        }
        return list.get(0);
    }
}

Then think about the law
Suppose the answer to this question is f(n, m)
Then the first deleted position is M% N, and then the position m%n+1 becomes the initial position of the problem of f(n -1, m), that is, the zero position
After deleting one, the problem becomes f(n - 1, m), assuming that the solution of the problem is x
Then the answer to the question of f(n, m) should be to move x positions on the basis of M% n positions
Recursion can be written, dynamic programming saves space

class Solution {
    public int lastRemaining(int n, int m) {
        int pre = 0;
        for(int i = 2; i <= n; i++){
            int f = (m + pre) % i;
            pre = f;
        }
        return pre;
    }
}

Topics: Java leetcode