java数据结构与算法刷题-----LeetCode1005. K 次取反后最大化的数组和(这就不是简单题)

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

卷来卷去,把简单题都卷成中等题了

文章目录

    • 1. 排序后从小到大取负
    • 2. hash表从小到大排序,省掉排序(这就是为什么这题不是简单题)

在这里插入图片描述

1. 排序后从小到大取负

解题思路:时间复杂度O( n ∗ l o g 2 n n*log_{2}n nlog2n),时间复杂度的大头就是排序算法. 空间复杂度O( l o g 2 n log_{2}n log2n),快速排序算法需要栈空间

将数组排序后,从小到大取负即可

代码

在这里插入图片描述

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        // 排序,把可能有的负数排到前面
        Arrays.sort(nums);
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            // 贪心:如果是负数,而k还有盈余,就把负数反过来
            if (nums[i] < 0 && k > 0) {
                nums[i] = -1 * nums[i];
                k--;
            }
            sum += nums[i];
        }
        Arrays.sort(nums);
        // 如果k没剩,那说明能转的负数都转正了,已经是最大和,返回sum
        // 如果k有剩,说明负数已经全部转正,所以如果k还剩偶数个就自己抵消掉,不用删减,如果k还剩奇数个就减掉2倍最小正数。
        return sum - (k % 2 == 0 ? 0 : 2 * nums[0]); 
    }
}

2. hash表从小到大排序,省掉排序(这就是为什么这题不是简单题)

上面方法一,排序浪费了大量时间,这个方法,将排序的时间省下来了 , 一举将这道简单题,升为中等难度的题。

解题思路:时间复杂度O( n + c n+c n+c),n是数组长度,c是数组中元素的取值范围. 空间复杂度O( C C C)
  1. 先将数组所有数字放入hash表统计其在数组中出现的次数,并且统计数组的所有元素和sum
  2. 然后从小到大依次对hash表中的负数取负(因为是负数,越小,取负后就越大。比如-100 和0 ,明显-100更小,但是取负后,变为100和0,100反而更大)
  3. 共取负k次,取负的过程中,修改sum的值,如何修改呢?这个是个固定套路。

将sum中的某一个负数(-x)改为正数(x),需要加两倍的x. 例如5 + (-1) = 4 , -1取负后结果为 5 + 1 = 6; ==> 4 + 1*2 = 6。也就是sum + (-x) = newSum, 取负 newSum + 2 * x = newNewSum

  1. 此时如果所有负数都取负完成,k依然没有归0,说明我们还需要继续取负。此时剩余的数字都是正数,所以我们对最小的数字取负即可。有以下两种情况
  1. 剩余k为偶数,因为-(-1) = 1.也就是对一个正数x取负偶数次,结果依然是x
  2. 剩余k为奇数,因为奇数-1为偶数。也就是我们对正数x先取负偶数次,结果依然是x次,然后再对其取负1次即可。简单来说,对剩余数字中最小的取负一次,然后对sum处理即可
  3. 注意:对一个sum中的一个正数取负,需要减去两个它。注意和上面将sum中一个负数取负区分。
代码
  1. 使用数组充当hash表的效率
    在这里插入图片描述
  2. 使用HashMap的效率(所以不使用这种方法,从而将这道题的难度又提升了一些)
    在这里插入图片描述

代码中的细节:普通使用hash表的效率很低,所以这道题想要超越100%的用户,需要使用数组充当hash表,这也是为什么这道题不是简单题的原因(新手很难转过来这个弯)

  1. 用数组充当hash表,因为题目所给取值范围为[-100 , 100],所以我们需要一个大小为201的数组充当hash表。也可以直接用HashMap(但是对于做题来说,效率就慢了)
  2. hash数组下标从0开始,则下标0代表-100.下标1代表-99,…,下标100代表0,…,下标200代表100
  3. 对于一个数字i来说,需要+100才是hash数组中对应的位置,因为-100+100 = 0,正好存在hash[0]的位置
  4. 既然hash[100]代表数字0,那么hash[100] 保存正数 hash[200]
  5. 对于一个负数来说,对其取负后,他变为正数,应该存放到hash[200-i]的位置,例如-100取负为100,-100原本在hash[0],则 i = 0. 此时变成正数后,应该存放到hash[200]. 也就是hash[200-(0)] ==>hash[200]
class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        int[] arr = new int[201];//hash表,这道题的范围是-100到100,正好需要201个位置存储。下标0表示-100
        int sum = 0;//保存当前nums数组的和
        for(int n : nums){
            arr[n+100]++;//统计元素出现次数
            sum += n;//统计当前所有元素的和
        }
        for(int i = 0; i < 100 && k > 0; i++){//从小到大遍历hash表中的负数
            if(arr[i] != 0){//如果当前数字还有剩余
                //如果当前数字i出现次数 < k ,则获取i的出现次数
                //如果当前数字i的出现次数 > k, 则获取k,表示剩余可以取负的次数
                int min = Math.min(arr[i],k);//获取当前数字的出现次数和k,较小的一个
                k -= min;//对当前数字i,每一个都取负,k表示可取负的次数,需要对min个i取负
                //负数取负后,变为正数,i = 0表示的是-100,取负变为100,应该存储在i = 200的位置,
                //i = 200表示的是正100
                arr[200-i] += min;//对min个i取负,则变为min个正i。存放到相应位置
                //5 + (-1) = 4 , 5 + 1 = 6; ==> 4 + 1*2 = 6 
                //sum + (-x) = newSum, 取负 newSum + 2 * x = newNewSum
                //当一个和的结果中,将一个负数取负后,需要加上两个它哦
                //我们这里只将负数转为正数,例如将i(0<=i<100)转为正数,是200-i
                //但是因为sum中取负某个负数i后,需要加上两个i,因此是200-2*i
                //我们一共取负了min个i,故需要(200-2*i) * min
                sum += (200-2*i)*min;
            }
        }
        //如果所有负数全部取负后,k还是没有归0,也就是我们必须继续对数字取负
        //因为k剩偶数个时,我们对同一个取负,结果不变,例如x取负两次,-(-x) = x
        //如果k还剩奇数个,就需要对某个数继续取负一次,因为 奇数 减去 1 为偶数,偶数次取负,原值不变,则剩一次需要取负
        if(k % 2 != 0){
            for(int i = 100; i <= 200; i++){//因为没有负数了,则对现存最小的数字取反一次即可
                if(arr[i] != 0){//如果当前数字存在
                    sum -= (i-100)*2;//对其取负,对一个sum中的一个正数取负,需要减去两个它
                    return sum;//返回最终结果
                }
            }
        }
        return sum;//如果在负数全部取负之前(正好全取负完)k就归0了,直接返回sum即可
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/468098.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据挖掘】练习2:数据管理2

课后作业2&#xff1a;数据管理2 一&#xff1a;上机实验2 # 编写函数stat&#xff0c;要求该函数同时计算均值&#xff0c;最大值&#xff0c;最小值&#xff0c;标准差&#xff0c;峰度和偏度。 install.packages("timeDate") library(timeDate) stat <- func…

论文笔记:液体管道泄漏综合检测与定位模型

0 简介 An integrated detection and location model for leakages in liquid pipelines 1 摘要 许多液体&#xff0c;如水和油&#xff0c;都是通过管道运输的&#xff0c;在管道中可能发生泄漏&#xff0c;造成能源浪费、环境污染和对人类健康的威胁。本文描述了一种集成的…

使用Composer安装Laravel框架

使用Composer安装Laravel框架&#xff0c;不指定版本则安装当下最新版本 composer create-project laravel/laravel laravel-demo 至此&#xff0c;安装框架完成&#xff0c;这里安装的是Laravel11.0.7版本的 进入项目根目录&#xff0c;运行项目 cd laravel.11.0.7 // 进…

JavaScript之继承

继承 父类与子类 子类是父类的一个子集 比如&#xff1a;人类和医生类&#xff0c;医生类是人类的子集&#xff1b;人类是父类&#xff0c;医生类是子集 父类与子类在特性&#xff08;属性和方法&#xff09;上有什么关系 方法&#xff1a;子类对象可以调用父类原型上的方…

Django 反向解析路由

app2.urls.py from django.urls import path, re_path from . import viewsurlpatterns [path(index, views.index, nameindex),path(url_reverse, views.url_reverse, nameapp2_url_reverse), # 使用reverse()方法反向解析 ,name对于视图的reverse("app2_url_reverse&…

LeetCode每日一题【54.螺旋矩阵】

思路&#xff1a;模拟&#xff0c;初始化上下左右4个方向的边界&#xff0c;逐步收缩&#xff0c;注意要及时判断元素是否已经放满&#xff0c;否则会放入多余元素 class Solution { public:vector<int> spiralOrder(vector<vector<int>>& matrix) {int…

Linux:Gitlab:16.9.2 (rpm包) 部署及基础操作(1)

1.基础环境 我只准备了一台gitlab服务器&#xff0c;访问就用真机进行访问&#xff0c;接下来介绍一下详细配置 centos7 内网ip:192.168.6.7 外网ip:172.20.10.4 运行内存&#xff1a;4G CPU:4核 先去配置基础环境 关闭防火墙以及selinux 再去下载基础的运行…

【Unity动画】Unity如何导入序列帧动画(GIF)

Unity 不支持GIF动画的直接播放&#xff0c;我们需要使用序列帧的方式 01准备好序列帧 02全部拖到Unity 仓库文件夹中 03全选修改成精灵模式Sprite 2D ,根据需要修改尺寸&#xff0c;点击Apply 04 创建一个空物体 拖动序列上去 然后全选所有序列帧&#xff0c;拖到这个空物体…

Kafka:分布式消息队列

1. 简介 介绍 Kafka 的概述、优势和劣势&#xff0c;以及应用场景。 2. 基本概念 2.1 架构 一个典型的 Kafka 体系架构包括若干 Producer、若干Broker、若干 Consumer&#xff0c;以及一个ZooKeeper集群。 ZooKeeper是Kafka用来负责集群元数据的管理、控制器的选举等操作的…

java的成员变量和局部变量

1、什么是成员变量和局部变量&#xff1f; 2、成员变量和局部变量区别 区别 成员变量 局部变量 类中位置不同 类中方法外 方法内或者方法声明上 内存中位置不同 堆内存 栈内存 生命周期不同 随着对象的存在而存在&#xff0c;随着对象的消失而消失 随着方法的调用而…

Kali Linux 更换优质国内源

文章目录 环境说明1 Kali Linux 源简介2 Kali Linux 更换国内源 环境说明 操作系统&#xff1a;kali-linux-2024.1-installer-amd64 1 Kali Linux 源简介 所谓的 Kali Linux 源&#xff0c;你可以将它理解为软件仓库&#xff0c;系统通过它安装和更新软件&#xff1b;源的服务…

人事管理系统|基于JSP+ Mysql+Java+ B/S结构的人事管理系统设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;ssm&#xff0c;springboot的平台设计与实现项目系统开发资源&#xff08;可…

vue3 reactive丢失响应式

问题 使用 reactive 构造响应式对象时&#xff0c;当对其进行重新赋值后&#xff0c;会导致原有变量失去响应式&#xff0c;页面不会发生联动更新 例如&#xff1a; 1、使用 reactive 定义一个响应式的对象变量 let data1 reactive({name: 小李,date: 2024-03-18,address: xx…

使用JAXB生成XML的Java对象

文章目录 标题使用JAXB生成XML的Java对象根据xml生成xsd文件&#xff1a;下载trang.jar&#xff1a;使用trang.jar生成xml的xsd文件&#xff1a; 使用JAXB的xjc生成java对象&#xff1a; 标题使用JAXB生成XML的Java对象 根据xml生成xsd文件&#xff1a; 下载trang.jar&#x…

Unity UGUI之Toggle基本了解

在Unity中&#xff0c;Toggle一般用于两种状态之间的切换&#xff0c;通常用于开关或复选框等功能。 它的基本属性如图&#xff1a; 其中&#xff0c; Interactable&#xff08;可交互&#xff09;&#xff1a;指示Toggle是否可以与用户交互。设置为false时&#xff0c;禁用To…

【Selenium(一)】

简介 Selenium是一个开源的自动化测试工具&#xff0c;主要用于Web应用程序的自动化测试。它支持多种浏览器&#xff0c;包括Chrome、Firefox、Internet Explorer等&#xff0c;以及多种编程语言&#xff0c;如Java、Python、C#、Ruby等&#xff0c;使得它成为Web自动化测试中…

学习笔记Day11:初探Linux

Linux系统初探 Linux系统简介 发行版本Ubuntu/centOS&#xff0c;逻辑一样&#xff0c;都可以用。 服务器 本质是一台远程电脑&#xff0c;大多数服务器是Linux系统&#xff0c;通常使用命令行远程访问而不是桌面操作。LInux服务器允许多用户同时访问。NGS组学测序数据上游…

Redis 7.0.X 在Windows下编译支持TLS连接,遇坑埋坑

微信公众号&#xff1a;数据库杂记 个人微信: iiihero 我是iihero. 也可以叫我Sean. iiheroCSDN(https://blog.csdn.net/iihero) Sean墨天轮 (https://www.modb.pro/u/16258) 数据库领域的资深爱好者一枚。 水木早期数据库论坛发起人 db2smth&#xff0c;早期多年水木论坛数…

VSCode创建用户代码片段-案例demo

示例 - 在线生成代码片段 Vue3代码片段 {"vue3": {scope": "javascript,typescript,html,vue","prefix": "vue3","body": ["<template>","$1","</template>",""…

Java后端面试:框架篇高频面试(Spring、SpringMVC、SpringBoot、MyBatis)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;Java后端面试&#xff1a;MySQL面试篇&#xff08;底层事务、SQL调优&#xff09; &#x1f4da;订阅专栏&#xff1a;Java后端面…