CS-Wiki CS-Wiki
Home
知识体系总览
  • 数据结构与算法
  • 计算机网络
  • 操作系统
  • MySQL
  • Redis
  • 设计模式
  • Java 基础
  • Java 集合
  • Java 并发
  • Java 虚拟机
  • Spring
  • Kafka
  • 校招扫盲
  • 项目推荐
  • 唠唠嗑儿
  • 读书笔记
归档
GitHub (opens new window)
Home
知识体系总览
  • 数据结构与算法
  • 计算机网络
  • 操作系统
  • MySQL
  • Redis
  • 设计模式
  • Java 基础
  • Java 集合
  • Java 并发
  • Java 虚拟机
  • Spring
  • Kafka
  • 校招扫盲
  • 项目推荐
  • 唠唠嗑儿
  • 读书笔记
归档
GitHub (opens new window)
  • 刷题模板汇总
  • 一些刷题小技巧
  • 整数 and 位运算

  • 数组

  • 链表

  • 哈希表

  • 字符串

  • 栈

  • 队列

  • 二叉树

  • 前缀树

  • 二分查找

  • 双指针法

  • 区间求和问题

  • 排序

  • 回溯算法

  • 贪心算法

    • 贪心算法理论基础
    • 找零
    • 柠檬水找零
    • 分发饼干
    • K 次取反后最大化的数组和
      • 📃 题目描述
      • 🔔 解题思路
      • 💥 复杂度分析
    • 加油站
    • 分发糖果
    • 根据身高重建队列
    • 划分字母区间
    • 单调递增的数字
    • 监控二叉树
    • 使数组变成交替数组的最少操作数
    • 剑指 Offer 14- II - 剪绳子 II
    • 区间调度问题

  • 动态规划

  • 图

  • 数学

  • 自动机

  • 海量数据和空间限制

  • 05-数据结构与算法
  • 贪心算法
小牛肉
2022-03-20
目录

K 次取反后最大化的数组和

# 📃 题目描述

题目链接:1005. K 次取反后最大化的数组和 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)

给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:

  • 选择某个下标 i 并将 nums[i] 替换为 -nums[i]
  • 重复这个过程恰好 k 次。可以多次选择同一个下标 i

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

示例 1:

输入:nums = [4,2,3], k = 1
输出:5
解释:选择下标 1 ,nums 变为 [4,-2,3]

示例 2:

输入:nums = [3,-1,0,2], k = 3
输出:6
解释:选择下标 (1, 2, 2) ,nums 变为 [3,1,0,2]

示例 3:

输入:nums = [2,-3,-1,5,-4], k = 2
输出:13
解释:选择下标 (1, 4) ,nums 变为 [2,3,-1,5,4]

# 🔔 解题思路

这里有两个贪心思想:

1)优先选择绝对值大的负数进行取反

2)如果负数全部取反后 k 还是大于 0:

  • k 为偶数,则直接返回结果就行了(比如 nums = [3,-1,0,2], k = 3,负数全部取反后,k = 2,此时 nums = [3, 1, 0, 2], nums 全部为正数的情况就是能够得到的最大和,此时我们只需要对任意一个数取反两次即保持不变就行)
  • k 为奇数,则对最小的这个正数取反奇数次(即把最小的正数变为负数)

Comparator 只支持引用类型,对于 int[] 类型的数组,是没有办法直接传进去的,需要转成 Integer 类型数组。可以用 Stream 流来简化操作

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        if (nums == null || nums.length == 0) {
            return 0;
        }

        // 按照绝对值大小降序排序
        // IntStream.of() 填充一个或多个int元素构造流
        // IntStream.boxed() 方法返回一个由该流元素组成的 Stream,每个元素都装箱为一个 Integer
        // mapToInt 使用映射函数处理流中的每一个元素, 并返回一个新的 IntStream
        nums = IntStream.of(nums).boxed().sorted(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Math.abs(o2) - Math.abs(o1);
            }
        }).mapToInt(Integer::intValue).toArray();

        // 优先取反绝对值大的负数
        for (int i = 0; i < nums.length; i ++) {
            if (nums[i] < 0 && k > 0) {
                nums[i] *= -1;
                k --;
            }
        }

        // 如果负数全部取反后 k 还是大于 0
        if (k % 2 == 1) {
            // k 为奇数,则对最小的这个正数取反奇数次(即把最小的正数变为负数)
            nums[nums.length - 1] *= -1;
        }

        // k 为偶数或者 k == 0,则直接返回结果就行了
        return Arrays.stream(nums).sum();
    }
}

image-20220110120028132

# 💥 复杂度分析

  • 空间复杂度:O(1)
  • 时间复杂度:O(NLogN),主要是排序的耗时

🎁 公众号

各位小伙伴大家好呀,叫我小牛肉就行,目前在读东南大学硕士,上方扫码关注公众号「飞天小牛肉」,与你分享我的成长历程与技术感悟~

帮助小牛肉改善此页面 (opens new window)
Last Updated: 2023/02/16, 11:27:10
分发饼干
加油站

← 分发饼干 加油站→

最近更新
01
关于编程满天星
02
让我来告诉你 Java 程序员是怎么一步一步从入行到被裁的
06-08
03
Vision Pro,未来已来
06-06
更多文章>
Theme by Vdoing | Copyright © 2019-2023 飞天小牛肉 | 皖ICP备2022008966号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式