LeetCode Record 02 - Novice Village Album (1)

topic

1480 Dynamic sum of one-dimensional array

1480 Dynamic sum of one-dimensional array

You are given an array nums. The formula for calculating the "dynamic sum" of the array is: runningSum[i] = sum(nums[0]…nums[i]).
Please return the dynamic sum of nums.

Example 1:
Input: nums = [1,2,3,4]
Output: [1,3,6,10]
Explanation: The dynamic and calculation process is [1, 1+2, 1+2+3, 1+2 +3+4] .

Example 2:
Input: nums = [1,1,1,1,1]
Output: [1,2,3,4,5]
Explanation: The dynamic and calculation process is [1, 1+1, 1+1+1 , 1+1+1+1, 1+1+1+1+1] .

Example 3:
Input: nums = [3,1,2,10,1]
Output: [3,4,6,16,17]

my train of thought

According to the given array dynamics and calculation formula and the explanation of the example, it can be known that: the i-th value is the cumulative sum of the previous data, and the previous item has saved all the previous data sum of this item.
insert image description here

It's a bit confusing, like nonsense literature, just go to the code to see it

my code

class Solution {
    
    
    public int[] runningSum(int[] nums) {
    
    
    	//定义一个数组来储存动态和的结果
        int[] sums = new int[nums.length];
        //定义一个变量计算累加和
        int sum = 0;
        //遍历目标数组
        for (int i = 0; i < nums.length; i++) {
    
    
            sum += nums[i];
            //将前面i项的累加和赋值给动态和数组
            sums[i]=sum;
        }
        //返回动态和数组
        return sums;
    }
}

Submit results

insert image description here
From the submission results, we can see that such an idea consumes too much memory, and an additional array is created to store data, so it is conceivable to use the local target array for direct calculation, and the code can be updated to the following form:

Code optimization

class Solution {
    
    
    public int[] runningSum(int[] nums) {
    
    
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
    
    
            sum += nums[i];
            //累加完直接赋值给当前下标的数组元素
            nums[i]=sum;
        }
        return nums;
    }
}

insert image description here
In this way, an O(n) memory consumption can be saved, and the definition of variables can be directly omitted, and dynamic programming can be used directly. Note: at this time, the traversal starts from the array subscript 1.

class Solution {
    
    
    public int[] runningSum(int[] nums) {
    
    
    	//数组从下标1开始遍历,第一项就是其本身,从第二项开始,每一项更新为  当前值与上一项的值  的和
        for (int i = 1; i < nums.length; i++) {
    
    
            nums[i] += nums[i-1];
        }
        return nums;
    }
}

insert image description here
But this memory consumption is a bit larger than the previous optimized code, it should be because each sum accesses the value in the array twice.

Summarize

You may not think of the optimal solution at the beginning, but you can try to further optimize it, and judge the pros and cons of the algorithm through the reference values ​​of execution time and memory consumption fed back by the Likou platform. And this advantage and disadvantage are not eternal, but have different uses for different problems. For example, in practice, it may be necessary to exchange space for time, and similarly, it may be necessary to exchange time for space.

383 ransom letter

383 ransom letter

Given you two strings: ransomNote and magazine, judge whether ransomNote can be composed of characters in magazine.
Returns true if it can; otherwise returns false.
Each character in magazine can only be used once in ransomNote.

Example 1:
Input: ransomNote = "a", magazine = "b"
Output: false

Example 2:
Input: ransomNote = "aa", magazine = "ab"
Output: false

Example 3:
Input: ransomNote = "aa", magazine = "aab"
Output: true

my train of thought

Key: According to the meaning of the question, ransomNote is composed of magazine characters and can only be used once , so it can be converted to compare the number of characters of two characters . Obviously, the string length of ransomNote cannot be greater than the string length of magazine, ransonNote.length()>magazine/length()even if you can directly skip the comparison and return false.

I thought of comparing the number of characters in the two strings, but I don't know how to start writing the code. At first I thought of using the Map type to store characters and their corresponding numbers, but it was very troublesome. How to compare when there is a letter difference (that is, only one of the strings contains the letter).
I googled "count the number of letters in a string", and when I saw the code 26和'a', I figured it out.

Conclusion: directly define an array of int type int[] chars = new int[26]to store the number of occurrences of each letter, and the storage position is determined by the traversed letter-'a'( s.charAt(i)-'a') (the char type can be represented by the ASCII code of the int type), and the prompt has explained that all It is a lowercase English letter, so there is no need to consider capitalization. Therefore, after calculating the array returned by the number of letters in the two strings, you can compare them. As long as the number of letters in ransomNote is greater than that in magazine , false will be returned.

my code

class Solution {
    
    
    public boolean canConstruct(String ransomNote, String magazine) {
    
    
    	//被组成的数组长度都大于源数组长度,还比什么,可以直接跳了
        if(ransomNote.length()>magazine.length()){
    
    
            return false;
        }
        //计算ransomNote的字符数量数组
        int countR[] = count(ransomNote);
        //计算magazine的字符数量数组
        int countM[] = count(magazine);
        boolean flag =true;
        for (int i =0;i< 26;i++) {
    
    
        	//只要ransomNote中的字符数量大于magazine的,就已经无法由后者组成了,所以可以停止循环返回false
            if (countR[i]>countM[i]){
    
    
                flag =false;
                break;
            }
        }
        return flag;
    }
    //自定义的计算字符数目的方法,返回值int[]
    public static int[] count(String s){
    
    
        int[] chars = new int[26];
        for (int i = 0; i < s.length(); i++) {
    
    
        	//例如字母a,存储在char[0]中,b--->char[1],c--->char[2]...
            chars[s.charAt(i)-'a']++;
        }
        return chars;
    }
}

Submit results

insert image description here
According to the code and submission results, the memory consumption is very large, and further optimization of the code can be considered.

Code optimization

You can try to use only one int[] array to store the number of letters, for example, ransomNotewhen counting the number of letters in the statistics ++, and counting magazinethe number --, and finally loop through the int[] array, as long as there is a value > 0 (that is, the characters in the magazine If the number is not enough to form ransomNote), you can return false

class Solution {
    
    
    public boolean canConstruct(String ransomNote, String magazine) {
    
    
        if(ransomNote.length()>magazine.length()){
    
    
            return false;
        }
        boolean flag =true;
        //只定义了一个int类型的数组
        int[] chars = new int[26];
        //分别对两个字符串循环遍历
        for (int i = 0; i < ransomNote.length(); i++) {
    
    
            chars[ransomNote.charAt(i)-'a']++;
        }
        for (int i = 0; i < magazine.length(); i++) {
    
    
            chars[magazine.charAt(i)-'a']--;
        }
        for (int i =0;i< 26;i++) {
    
    
        	//char[i]>0表示ransomNote的某个字母数大于magazine
            if (chars[i]>0){
    
    
                flag =false;
                break;
            }
        }
        return flag;
    }
}

insert image description here
Although it traverses three times, it consumes less memory than array operations.
Of course, you can also think about it the other way around, so you can save one more loop traversal.

class Solution {
    
    
    public boolean canConstruct(String ransomNote, String magazine) {
    
    
        if(ransomNote.length()>magazine.length()){
    
    
            return false;
        }
        int[] chars = new int[26];
        //先计算准备赎金中的字符数量
        for (int i = 0; i < magazine.length(); i++) {
    
    
            chars[magazine.charAt(i)-'a']++;
        }
        for (int i = 0; i < ransomNote.length(); i++) {
    
    
        	//扣除花掉的赎金字符数量
            chars[ransomNote.charAt(i)-'a']--;
            //小于0则说明magazine中的赎金(字符)不够
            if(chars[ransomNote.charAt(i)-'a']<0){
    
    
                return false;
            }
        }
        return true;
    }
}

insert image description here
However, the memory consumption seems to be quite large, and it should also be the pot for accessing the array.

Summarize

The key to this question is to use only one conversion and compare the number of characters , and my biggest achievement is: through the connection between char type and int type, you can easily use array subscripts to represent letters, and the array elements A value can be used to store the number of occurrences of a letter. This kind of thinking also needs more practice to form its own DNA memory.

Guess you like

Origin blog.csdn.net/weixin_51229662/article/details/127818474