zoukankan      html  css  js  c++  java
  • leetcode

    1155. 掷骰子的N种方法


    这里有 d 个一样的骰子,每个骰子上都有 f 个面,分别标号为 1, 2, ..., f

    我们约定:掷骰子的得到总点数为各骰子面朝上的数字的总和。

    如果需要掷出的总点数为 target,请你计算出有多少种不同的组合情况(所有的组合情况总共有 f^d 种),模 10^9 + 7 后返回。

    示例 1:

    输入:d = 1, f = 6, target = 3
    输出:1
    

    示例 2:

    输入:d = 2, f = 6, target = 7
    输出:6
    

    示例 3:

    输入:d = 2, f = 5, target = 10
    输出:1
    

    示例 4:

    输入:d = 1, f = 2, target = 3
    输出:0
    

    示例 5:

    输入:d = 30, f = 30, target = 500
    输出:222616187

    提示:

    • 1 <= d, f <= 30
    • 1 <= target <= 1000
    var numRollsToTarget = function(d, f, target) {
        const cache = {}
        return ways(d, target)
        function ways(d, target) {
            const key = d + ',' + target
            if (cache[key] !== undefined) return cache[key]
            if (d <= 1) {
                if (target > 0 && target <= f) return (cache[key] = 1)
                return (cache[key] = 0)
            }
            let sum = 0
            for (let i = 1; i <= f; i++) {
                if (target <= i) continue
                sum += ways(d - 1, target - i)
            }
            return (cache[key] = sum % (10 ** 9 + 7))
        }
        // 不行,超时间限制
        // return ways(d, target);
        // function ways(d, target){
        //     if(d<=1){
        //         if(target >0 && target<=f) return 1;
        //         return 0
        //     }
        //     let sum = 0;
        //     for(let i=1; i<=f; i++){
        //         if(target <=i ) continue
        //         sum += ways(d-1, target-i)
        //     }
        //     return sum % (10**9 + 7)
        // }
    };
    

      // 像这种出现类似操作的肯定是可以用递归解决的,low点的办法就是拼接字符串,eval

    5130. 等价多米诺骨牌对的数量

    给你一个由一些多米诺骨牌组成的列表 dominoes

    如果其中某一张多米诺骨牌可以通过旋转 0 度或 180 度得到另一张多米诺骨牌,我们就认为这两张牌是等价的。

    形式上,dominoes[i] = [a, b] 和 dominoes[j] = [c, d] 等价的前提是 a==c 且 b==d,或是 a==d 且 b==c

    在 0 <= i < j < dominoes.length 的前提下,找出满足 dominoes[i] 和 dominoes[j] 等价的骨牌对 (i, j) 的数量。

    示例:

    输入:dominoes = [[1,2],[2,1],[3,4],[5,6]]
    输出:1
    

    提示:

    • 1 <= dominoes.length <= 40000
    • 1 <= dominoes[i][j] <= 9
    /**
     * @param {number[][]} dominoes
     * @return {number}
     */
    var numEquivDominoPairs = function(dominoes) {
         let hash = new Map();
    
        let ans = 0;
        for(let dom of dominoes){
            let key=dom.sort((a,b)=>a-b).join(":");
            let val = hash.get(key)||0
            if(val>0){
                ans+=val;
            }
            hash.set(key,val+1);
        }
        return ans;
    };
    let hash={}
      let memo={}
      for(let i=0;i<dominoes.length;i++){
        let [f,e]=dominoes[i]
        let min=Math.min(f,e)
        let max=Math.max(f,e)
        if(hash[min+' '+max]==null)hash[min+' '+max]=1
        else hash[min+' '+max]++
      }
      
      let res=0
      for(let k in hash){
        res+=add(hash[k]-1)
      }
      
      return res
      function add(n){
        let res=0
        for(let i=1;i<=n;i++){
          res+=i
        }
        return res
      }

    反思:

    悲哀,自己只会用双层for循环,导致测试用例总是超出时间限制,所以存在效率性问题可以考虑下set、map数据结构。

    5128. 最深叶节点的最近公共祖先(二叉树)

    给你一个有根节点的二叉树,找到它最深的叶节点的最近公共祖先。

    回想一下:

    • 叶节点 是二叉树中没有子节点的节点
    • 树的根节点的 深度 为 0,如果某一节点的深度为 d,那它的子节点的深度就是 d+1
    • 如果我们假定 A 是一组节点 S 的 最近公共祖先,s 中的每个节点都在以 A 为根节点的子树中,且 A 的深度达到此条件下可能的最大值。

    示例 1:

    输入:root = [1,2,3]
    输出:[1,2,3]
    

    示例 2:

    输入:root = [1,2,3,4]
    输出:[4]
    

    示例 3:

    输入:root = [1,2,3,4,5]
    输出:[2,4,5]
    

    提示:

    • 给你的树中将有 1 到 1000 个节点。
    • 树中每个节点的值都在 1 到 1000 之间。
    /**
     * Definition for a binary tree node.
     * function TreeNode(val) {
     *     this.val = val;
     *     this.left = this.right = null;
     * }
     */
    /**
     * @param {TreeNode} root
     * @return {TreeNode}
     */
    var lcaDeepestLeaves = function(root) {
      let parent=null
      let maxLevel=0
      deep(root,0)
      return parent
      function deep(root,level){
        if(!root)return 0
    
        let left=deep(root.left,level+1)
        let right=deep(root.right,level+1)
        let max=Math.max(left,right)+1
        maxLevel=Math.max(maxLevel,level)
        if(left===right){
          if(level+left===maxLevel || max===maxLevel){
            parent=root
          }
        }
        return max
      }
    };

    解析:

    有必要深入探讨

    1094. 拼车

    假设你是一位顺风车司机,车上最初有 capacity 个空座位可以用来载客。由于道路的限制,车 只能 向一个方向行驶(也就是说,不允许掉头或改变方向,你可以将其想象为一个向量)。

    这儿有一份行程计划表 trips[][],其中 trips[i] = [num_passengers, start_location, end_location] 包含了你的第 i 次行程信息:

    • 必须接送的乘客数量;
    • 乘客的上车地点;
    • 以及乘客的下车地点。

    这些给出的地点位置是从你的 初始 出发位置向前行驶到这些地点所需的距离(它们一定在你的行驶方向上)。

    请你根据给出的行程计划表和车子的座位数,来判断你的车是否可以顺利完成接送所用乘客的任务(当且仅当你可以在所有给定的行程中接送所有乘客时,返回 true,否则请返回 false)。

    示例 1:

    输入:trips = [[2,1,5],[3,3,7]], capacity = 4
    输出:false
    

    示例 2:

    输入:trips = [[2,1,5],[3,3,7]], capacity = 5
    输出:true
    

    示例 3:

    输入:trips = [[2,1,5],[3,5,7]], capacity = 3
    输出:true
    

    示例 4:

    输入:trips = [[3,2,7],[3,7,9],[8,3,9]], capacity = 11
    输出:true
    

    提示:

    1. 你可以假设乘客会自觉遵守 “先下后上” 的良好素质
    2. trips.length <= 1000
    3. trips[i].length == 3
    4. 1 <= trips[i][0] <= 100
    5. 0 <= trips[i][1] < trips[i][2] <= 1000
    6. 1 <= capacity <= 100000
    /**
     * @param {number[][]} trips
     * @param {number} capacity
     * @return {boolean}
     */
    function carPooling(trips, capacity) {
       let a =new Array(1000).fill(0);
        for(let i = 0; i < trips.length; i++){
            for(let j = trips[i][1]; j < trips[i][2]; j++){
                a[j] += trips[i][0];
                if(a[j] > capacity){
                    return false;
                }
            }
        }
        return true;
    }    
    // 这个题之前见过类似的。
    /*
    var carPooling = function(trips, capacity) {
        let passengers = [],
            locations = [];
        trips.forEach((trip)=>{
            passengers.push(trip[0]);
            locations.push([trip[1], trip[2]]);
        })
        for(let i=0; i<locations.length; i++){
            let pas = passengers[i];
            for(let j=1; j<locations.length; j++){
                let loc = (locations[i][0]<locations[j][0] && locations[i][1] >locations[j][0]) || (locations[i][0]>locations[j][0] && locations[j][1]>locations[i][0])
                if(loc){
                   pas+= passengers[j];
                   if(pas>capacity) return false;
                }
            }
        }
        return true
    };
    */

    这种类型的题这么多,今天还是没做出来

    1109. 航班预订统计(数组)

    这里有 n 个航班,它们分别从 1 到 n 进行编号。

    我们这儿有一份航班预订表,表中第 i 条预订记录 bookings[i] = [i, j, k] 意味着我们在从 i 到 j 的每个航班上预订了 k 个座位。

    请你返回一个长度为 n 的数组 answer,按航班编号顺序返回每个航班上预订的座位数。

    示例:

    输入:bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5
    输出:[10,55,45,25,25]
    

    提示:

    • 1 <= bookings.length <= 20000
    • 1 <= bookings[i][0] <= bookings[i][1] <= n <= 20000
    • 1 <= bookings[i][2] <= 10000
    /**
     * @param {number[][]} bookings
     * @param {number} n
     * @return {number[]}
     */
    /*
    // 20000个航班就不行了
    var corpFlightBookings = function(bookings, n) {
        let res =[];
        let sum = 0;
        for(let i=1; i<=n; i++){
            sum = 0;
            for(let j=0; j<bookings.length; j++){
                if(i>=bookings[j][0] && i<=bookings[j][1]){
                    sum += bookings[j][2];
                }
            }
            res.push(sum);
        }
        return res;
    };
    */
    
    
    var corpFlightBookings = function(bookings, n) {
        const res = Array(n).fill(0)
        bookings.forEach(v => {
            // v[1]-v[0] 必然是小于等于20000的
            for (let i = v[0]; i <= v[1]; i++) {
                res[i - 1] += v[2]
            }
        })
        return res
    };

    个人理解:

    之前的写法会内存溢出,可以考虑每个条记录的前两个元素正是某个区域的航班,必然小于n个航班;由原来的push操作,直接变为赋值操作。

    5129. 表现良好的最长时间段(数组)

    给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数。

    我们认为当员工一天中的工作小时数大于 8 小时的时候,那么这一天就是「劳累的一天」。

    所谓「表现良好的时间段」,意味在这段时间内,「劳累的天数」是严格 大于「不劳累的天数」。

    请你返回「表现良好时间段」的最大长度。

    示例 1:

    输入:hours = [9,9,6,0,6,6,9]
    输出:3
    解释:最长的表现良好时间段是 [9,9,6]。

    提示:

    • 1 <= hours.length <= 10000
    • 0 <= hours[i] <= 16

    题目链接:

    https://leetcode-cn.com/contest/weekly-contest-145/problems/longest-well-performing-interval/

    /**
     * @param {number[]} hours
     * @return {number}
     */
    var longestWPI = function(hours) {
        let arr = [];
        for (var i = 0; i < hours.length; i++) {
            for (var j = i+1; j <= hours.length; j++) {
                let lao=0, xiu=0, subArr = hours.slice(i, j);
                subArr.forEach(s=>{
                    if(s>8){
                        lao++
                    }else {
                        xiu++
                    }
                })
                if(lao>xiu){
                    pushArr(arr, subArr);
                }
                
            }
        }
        if(!arr.length) return 0;
        let maxLenArr = arr[0];
        for (var i = 1; i < arr.length; i++) {
            if(arr[i].length>maxLenArr.length){
                maxLenArr = arr[i]
            }
        }
        return maxLenArr.length;
    };
    let pushArr =function(arr, subArr){
        arr.push({
                subArr: subArr,
                length: subArr.length
            });
    }
    /**
     * @param {number[]} hours
     * @return {number}
     */
    var longestWPI = function(hours) {
         let n = hours.length;
         let array = new Array(n);
        for(let i = 0; i < n; i++){
            if(hours[i] > 8)
                array[i] = 1;
            else
                array[i] = -1;
        }
        let ans = 0;
        for(let i = 0; i < n; i++){
            let temp = 0;
            for(let j = i; j < n; j++){
                temp += array[j];
                if(temp > 0)
                    ans = Math.max(ans, j-i+1);
            }
        }
        return ans;
    };

    个人理解:

    这种双层for循环对子数组进行处理的问题。

    像这种求最值,多层循环又会出现内存溢出的问题。
    总是会出现额外的数组,还有Math.max之类的。

    1005. K 次取反后最大化的数组和  VS 1002.查找常用字符

    给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次。(我们可以多次选择同一个索引 i。)

    以这种方式修改数组后,返回数组可能的最大和。

    示例 1:

    输入:A = [4,2,3], K = 1
    输出:5
    解释:选择索引 (1,) ,然后 A 变为 [4,-2,3]。
    

    示例 2:

    输入:A = [3,-1,0,2], K = 3
    输出:6
    解释:选择索引 (1, 2, 2) ,然后 A 变为 [3,1,0,2]。
    

    示例 3:

    输入:A = [2,-3,-1,5,-4], K = 2
    输出:13
    解释:选择索引 (1, 4) ,然后 A 变为 [2,3,-1,5,4]。
    

    提示:

    1. 1 <= A.length <= 10000
    2. 1 <= K <= 10000
    3. -100 <= A[i] <= 100
    /**
     * @param {number[]} A
     * @param {number} K
     * @return {number}
     */
    var largestSumAfterKNegations = function(A, K) {
        A.sort((a, b)=> a-b);
        let a=0;
        A.forEach(item=>{
           if(item<=0) a++; 
        })
        if(a<=K){
            A = A.map(a=>Math.abs(a));
            if((K-a)%2){
                A.sort((a, b)=> a-b);
                A[0] = -A[0];
            }
            return A.reduce((init, val)=>init+val)
        } else {
            for(let i=0; i<K; i++){
                A[i] = -A[i]
            }
            return A.reduce((init, val)=>init+val, 0);
        }
        
    };

    想法:

    开始想的是要在[0, A.length-1]里面取K次,把所有的可能遍历一遍,然后Math.max();其实也想到排一下序也可以ok(也许排下序列,真的会有新的想法)。还想了,要不也拼一下字符串然后eval。

    994. 腐烂的橘子

    994. 腐烂的橘子

    在给定的网格中,每个单元格可以有以下三个值之一:

    • 值 0 代表空单元格;
    • 值 1 代表新鲜橘子;
    • 值 2 代表腐烂的橘子。

    每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。

    返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1

    输入:[[2,1,1],[1,1,0],[0,1,1]]
    输出:4
    

    示例 2:

    输入:[[2,1,1],[0,1,1],[1,0,1]]
    输出:-1
    解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个正向上。
    

    示例 3:

    输入:[[0,2]]
    输出:0
    解释:因为 0 分钟时已经没有新鲜橘子了,所以答案就是 0 。
    

    提示:

    1. 1 <= grid.length <= 10
    2. 1 <= grid[0].length <= 10
    3. grid[i][j] 仅为 01 或 2
        var orangesRotting = function(grid) {
        if(grid.length === 0) return 0;
        let enumOrange = [[1,0],[0,1],[-1,0],[0,-1]],
            freshNum = 0,
            rots = [],
            x = grid.length,
            y = grid[0].length,
            step=0;
        for(let i=0; i<x; i++){
            for(let j=0; j<y; j++){
                if(grid[i][j] === 1){
                    freshNum++;
                }else if(grid[i][j]===2){
                    rots.push([i, j])
                }
            }
        }
        if(freshNum === 0) return 0;
        while(rots.length){
            if(freshNum === 0) return step;
            step++;
            let num = rots.length;
            for (let i = 0; i < num; i++) {
                let curr = rots.shift();
                for(let k=0; k<enumOrange.length; k++){
                    let m = enumOrange[k][0],
                        n = enumOrange[k][1];
                    let next = grid[curr[0]+m] && grid[curr[0]+m][curr[1]+n];
                    if(next===1){
                        grid[curr[0]+m][curr[1]+n] = 2;
                        rots.push([curr[0]+m, curr[1]+n]);
                        freshNum--;
                    } 
                }
            };
        }
        return -1
    }

    复盘:

    枚举类型和for of的应用

     1002.查找常用字符

    给定仅有小写字母组成的字符串数组 A,返回列表中的每个字符串中都显示的全部字符(包括重复字符)组成的列表。例如,如果一个字符在每个字符串中出现 3 次,但不是 4 次,则需要在最终答案中包含该字符 3 次。

    你可以按任意顺序返回答案。

    示例 1:

    输入:["bella","label","roller"]
    输出:["e","l","l"]
    

    示例 2:

    输入:["cool","lock","cook"]
    输出:["c","o"]
    

    提示:

    1. 1 <= A.length <= 100
    2. 1 <= A[i].length <= 100
    3. A[i][j] 是小写字母

    解答:

    /**
     * @param {string[]} A
     * @return {string[]}
     */
    var commonChars = function(A) {
        let res = [];
        let arr1 = A.map(a=>{
            return a.split('')
        });
        
        for(let j=0; j<arr1[0].length; j++){
             let a1 = arr1[0][j],
                 count = 0;
            for(let i=1; i<arr1.length; i++){
                let subArr = arr1[i],
                    index = subArr.indexOf(a1);
                if(index<0){
                    break;
                } else {
                    subArr.splice(index, 1)
                    count++;
                }
            }   
            if(count === arr1.length-1) {
                res.push(a1)
            }
        }
        
        return res;
    };

    复盘:

    当时没考虑数组的长度,以为都是3,所有3个循环然后splice;如果不是3个是n个呢,像这种最low的方法就是拼接字符串eval。

    像这种拿第一个数组的元素分别循环剩下的元素可以用一个计算器count,判断count是否等于除第一个外,剩下数组的个数。

    1138. 字母板上的路径

    我们从一块字母板上的位置 (0, 0) 出发,该坐标对应的字符为 board[0][0]

    在本题里,字母板为board = ["abcde", "fghij", "klmno", "pqrst", "uvwxy", "z"].

    我们可以按下面的指令规则行动:

    • 如果方格存在,'U' 意味着将我们的位置上移一行;
    • 如果方格存在,'D' 意味着将我们的位置下移一行;
    • 如果方格存在,'L' 意味着将我们的位置左移一列;
    • 如果方格存在,'R' 意味着将我们的位置右移一列;
    • '!' 会把在我们当前位置 (r, c) 的字符 board[r][c] 添加到答案中。

    返回指令序列,用最小的行动次数让答案和目标 target 相同。你可以返回任何达成目标的路径。

    示例 1:

    输入:target = "leet"
    输出:"DDR!UURRR!!DDD!"
    

    示例 2:

    输入:target = "code"
    输出:"RR!DDRR!UUL!R!"
    

    提示:

    • 1 <= target.length <= 100
    • target 仅含有小写英文字母。
    /**
     * @param {string} target
     * @return {string}
     */
    
    // var alphabetBoardPath = function(target) {
    //     let board = ["abcde", "fghij", "klmno", "pqrst", "uvwxy", "z"];
    //     let map = new Map();
    //     for(let i=0; i<board.length; i++){
    //     	for(let j=0; j<board[i].length; j++){
    //     		map.set(board[i][j],[i, j])
    //     	}
    //     }
    //     let arr = target.split('');
    //     let sum = '';
    // 	for (var i = 0; i < arr.length; i++) {
    // 		let x, y;
    // 	    if(i===0){
    // 	    	[x, y] = map.get(arr[i]);
    // 	    } else {
    // 	    	let [x1, y1] = map.get(arr[i-1]);
    // 	    	let [x2, y2] = map.get(arr[i]);
    // 	    	x = x2-x1;
    // 	    	y = y2-y1;
    // 	    }
    // 	    let absX = Math.abs(x),
    // 	    	absY = Math.abs(y);
    	    
    // 	    if(x === 0 && y ===0){
    // 	    	sum+='!'
    // 	    } else {
    // 	    	if(x>0){
    // 	    		sum+=numsOfChar(absX, 'D', map);
    // 	    	}else {
    // 	    		sum+=numsOfChar(absX, 'U', map);
    // 	    	} 
    // 	    	if(y>0){
    // 	    		sum+=numsOfChar(absY, 'R', map);
    // 	    	} else {
    // 	    		sum+=numsOfChar(absY, 'L', map);
    // 	    	}
    // 	    	sum+='!'
    // 	    } 
    	
    // 	}
    // 	return sum; 
    // };
    // let numsOfChar= function(num, char, map){
    //     let map1 = {
    //         'D': [1, 0],
    //         'U': [-1, 0],
    //         'R': [0, 1],
    //         'L': [-1, 0]
    //     }
    // 	let res = '';
    // 	for (var i = 0; i < num; i++) {
    // 		res+=char
    // 	}
    // 	return res;
    // }
    
    var alphabetBoardPath = function(target) {
        const board = {}
        for (let i = 0; i < 26; i++) {
            board[String.fromCharCode(97 + i)] = [Math.floor(i / 5), i % 5]
        }
        let curCode = 'a'
        let res = []
        for (let i = 0, len = target.length; i < len; i++) {
            const cur = board[curCode]
            const newcur = board[target[i]]
            let flag = curCode === 'z' ? false : true
            if (flag) {
                if (newcur[1] >= cur[1]) res.push('R'.repeat(newcur[1] - cur[1]))
                else res.push('L'.repeat(cur[1] - newcur[1]))
                if (newcur[0] >= cur[0]) res.push('D'.repeat(newcur[0] - cur[0]))
                else res.push('U'.repeat(cur[0] - newcur[0]))
            } else {
                if (newcur[0] >= cur[0]) res.push('D'.repeat(newcur[0] - cur[0]))
                else res.push('U'.repeat(cur[0] - newcur[0]))
                if (newcur[1] >= cur[1]) res.push('R'.repeat(newcur[1] - cur[1]))
                else res.push('L'.repeat(cur[1] - newcur[1]))
            }
            curCode = target[i]
            res.push('!')
        }
        return res.join('')
    }
    

      复盘:

    它走路径如果超出边界会拐弯走,这个题,先走左右,后走上下就能避免走'z'的时候越界

    5182. 删除一次得到子数组最大和

    给你一个整数数组,返回它的某个 非空 子数组(连续元素)在执行一次可选的删除操作后,所能得到的最大元素总和。

    换句话说,你可以从原数组中选出一个子数组,并可以决定要不要从中删除一个元素(只能删一次哦),(删除后)子数组中至少应当有一个元素,然后该子数组(剩下)的元素总和是所有子数组之中最大的。

    注意,删除一个元素后,子数组 不能为空。

    请看示例:

    示例 1:

    输入:arr = [1,-2,0,3]
    输出:4
    解释:我们可以选出 [1, -2, 0, 3],然后删掉 -2,这样得到 [1, 0, 3],和最大。

    示例 2:

    输入:arr = [1,-2,-2,3]
    输出:3
    解释:我们直接选出 [3],这就是最大和。
    

    示例 3:

    输入:arr = [-1,-1,-1,-1]
    输出:-1
    解释:最后得到的子数组不能为空,所以我们不能选择 [-1] 并从中删去 -1 来得到 0。
         我们应该直接选择 [-1],或者选择 [-1, -1] 再从中删去一个 -1。

    提示:

    • 1 <= arr.length <= 10^5
    • -10^4 <= arr[i] <= 10^4
    var maximumSum = function(arr) {
        const r = [[null, null], [arr[0], null]]
        const len = arr.length
        let max = arr[0]
        for (let i = 1; i < len; i++) {
            const val = arr[i]
            // 计算第一种
            let res1 = val
            if (r[i][0] !== null && r[i][0] > 0) res1 = r[i][0] + val
            if (res1 > max) max = res1
            // 计算第二种
            let res2 = null
            if (r[i][1] !== null) res2 = r[i][1] + val
            if (r[i - 1][0] !== null) {
                if (res2 === null || r[i - 1][0] + val > res2)
                    res2 = r[i - 1][0] + val
            }
            if (res2 !== null && res2 > max) max = res2
            r.push([res1, res2])
        }
        return max
    }

    // 动态规划,数组保存了所有可能的值,求最大值

     

    K 次串联后最大子数组之和

    给你一个整数数组 arr 和一个整数 k

    首先,我们要对该数组进行修改,即把原数组 arr 重复 k 次。

    举个例子,如果 arr = [1, 2] 且 k = 3,那么修改后的数组就是 [1, 2, 1, 2, 1, 2]

    然后,请你返回修改后的数组中的最大的子数组之和。

    注意,子数组长度可以是 0,在这种情况下它的总和也是 0

    由于 结果可能会很大,所以需要 模(mod) 10^9 + 7 后再返回。 

    示例 1:

    输入:arr = [1,2], k = 3
    输出:9
    

    示例 2:

    输入:arr = [1,-2,1], k = 5
    输出:2
    

    示例 3:

    输入:arr = [-1,-2], k = 7
    输出:0
    

    提示:

    • 1 <= arr.length <= 10^5
    • 1 <= k <= 10^5
    • -10^4 <= arr[i] <= 10^4
    const p = 1e9 + 7
    // 数组和的最大值
    function work(arr) {
      let ans = 0
      let temp = 0
      for(let i = 0; i < arr.length; i++) {
        temp += arr[i]
        ans = Math.max(ans, temp)
        if (temp < 0) {
          temp = 0
        }
      }
      return ans
    }
    var kConcatenationMaxSum = function(arr, k) {
        let flag = true
        for(let i = 0; i < arr.length; i++) {
          if (arr[i] < 0) flag = false
        }
        const sum = arr.reduce((pre, item) => pre + item , 0)
        if (flag) {
          return (sum * k) % p
        }
        if (k === 1) {
          return work(arr) % p
        }
        if (k === 2) {
          return work([...arr, ...arr]) % p
        }
        if (sum > 0) {
          return (work([...arr, ...arr]) + ( k - 2) * sum ) % p
        } else {
          return work([...arr, ...arr]) % p
        }
    };

    反思: 如何求数组子数组的最大值,难道要把所有子数组列出来,求最大值吗?

    重复两个的规律?

  • 相关阅读:
    MySQL基础之 排序与限制,聚合
    AWS服务学习
    SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-006-定义切面使用xml
    SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-005-定义切面使用@Aspect、@EnableAspectJAutoProxy、<aop:aspectj-autoproxy>
    SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-004-使用AspectJ’s pointcut expression language定义Pointcut
    SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-003-Spring对AOP支持情况的介绍
    SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-002-AOP术语解析
    SPRING IN ACTION 第4版笔记-第四章Aspect-oriented Spring-001-什么是AOP
    SPRING IN ACTION 第4版笔记-第三章ADVANCING WIRING-009-用SPEL给bean运行时注入依赖值
    SPRING IN ACTION 第4版笔记-第三章ADVANCING WIRING-008-SpEL介绍
  • 原文地址:https://www.cnblogs.com/zhangzs000/p/11365119.html
Copyright © 2011-2022 走看看