题目描述

image.png

解题思路

贪心思路:
第一次贪心:(如果负数大于k)
局部最优:就是每次变换变换绝对值最大的数,整体最优:整个数组和达到最大。
第二次贪心:(如果负数小于k,负数变完之后,还剩正数)
局部最优:变换最小的正数,全局最优:整个 数组和 达到最大。
那么本题的解题步骤为:

  • 第一步:将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小
  • 第二步:从前向后遍历,遇到负数将其变为正数,同时K—
  • 第三步:如果K还大于0,那么反复转变数值最小的元素,将K用完
  • 第四步:求和

    写法一

    1. public int largestSumAfterKNegations(int[] A, int K) {
    2. if (A.length == 1) return K % 2 == 1 ? -A[0] : A[0];
    3. Arrays.sort(A);
    4. int index = 0;
    5. for (int i = 0; i < K; i++) {
    6. // 如果为负数,那就变为相反数
    7. if (i < A.length - 1 && A[index] < 0) {
    8. A[index] = -A[index];
    9. // 如果变化之后大于等于后边数的绝对值,那么index++
    10. // [1,3,2,6,7,9]
    11. // 3
    12. // 注意需要判断,否则全为正数就会不满足贪心
    13. if (A[index] >= Math.abs(A[index + 1])) index++;
    14. // 下一步不执行了
    15. continue;
    16. }
    17. // 最终负数消耗完了,但是还有正数,所以一直利用最小的一个正数,把k消耗完
    18. A[index] = -A[index];
    19. }
    20. // 统计总和
    21. int sum = 0;
    22. for (int i = 0; i < A.length; i++) {
    23. sum += A[i];
    24. }
    25. return sum;
    26. }

    写法二

    使用stream直接对绝对值排序

    1. public int largestSumAfterKNegations(int[] nums, int k) {
    2. int result = 0;
    3. // 将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小
    4. nums = IntStream.of(nums)
    5. .boxed()
    6. .sorted((o1, o2) -> Math.abs(o2) - Math.abs(o1))
    7. .mapToInt(Integer::intValue).toArray();
    8. for (int i = 0; i < nums.length; i++) {
    9. // 从前向后遍历,遇到负数将其变为正数,同时K--
    10. if (nums[i] < 0 && k > 0) {
    11. nums[i] = Math.abs(nums[i]);
    12. k--;
    13. }
    14. }
    15. if (k % 2 == 1) nums[nums.length - 1] = 0 - nums[nums.length - 1]; // 如果K还大于0,那么反复转变数值最小的元素,将K用完
    16. // 求和
    17. for (int i : nums) {
    18. result += i;
    19. }
    20. return result;
    21. }