HashCode与String大家庭

文章介绍了Java中hashCode的作用,用于优化集合中查找元素的效率,以及String、StringBuffer和StringBuilder的区别,特别是它们在字符串操作性能和线程安全性上的差异。此外,文章还讨论了二分查找算法,并给出一个在有序矩阵中寻找第K小元素的问题示例,提出了暴力和二分查找两种解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当金钱站起来说话时,所有的真理都保持了沉默;金钱一旦作响,坏话随之戛然而止。
在这里插入图片描述

Hashcode的作用

java的集合有两类,一类是List,还有一类是Set

前者有序可重复,后者无序不重复。当我们在set中插入的时候怎么判断是否已经存在该元素呢,可以通过equals方法。但是如果元素太多,用这样的方法就会比较慢。

于是有人发明了哈希算法来提高集合中查找元素的效率,这种方式将集合分成若干个存储区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象应该存储的那个区域

hashCode方法可以这样理解:它返回的就是根据对象的内存地址换算出的一个值。这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,他就可以直接存储在这个位置上,不用在进行任何比较了;如果这个位置上已经有了元素,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其他的地址,这样一来实际上调用equals方法的次数就大大降低了,几乎只需要一两次。

String、StringBuffer、StringBuilder

String是只读字符串,它并不是基本数据类型,而是一个对象,从底层源码来看是一个final类型的字符数组,所引用的字符串不能被改变,一经定义,无法再增删改查。每次对String的操作都会生成新的String对象

private final char value[];

每次+操作:隐式在堆上new了一个跟原字符串相同的StringBuffer对象,在调用append方法拼接+后面的字符

StringBuffer和StringBuilder他们两都继承了AbstractStringBuilder抽象类,从AbstractStringBuilder抽象类中我们可以看到

/**
* The value is used for character storage.
*/
char[] value;

他们的底层都是可变的字符数组,所以在进行频繁的字符串操作时,建议使用StringBuffer和StrignBuilder来进行操作

StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的,

StringBuilder并没有对方法进行加同步锁,所以是线程不安全的。
在这里插入图片描述

二分查找

题目:有序矩阵中第 K 小的元素

难度:🌟🌟🌟

来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/kth-smallest-element-in-a-sorted-matrix

给你一个 n x n 矩阵 matrix ,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。
请注意,它是 排序后 的第 k 小元素,而不是第 k 个 不同 的元素。

你必须找到一个内存复杂度优于 O(n2) 的解决方案。

示例 1:

输入:matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8
输出:13
解释:矩阵中的元素为 [1,5,9,10,11,12,13,13,15],第 8 小元素是 13

示例 2:

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

请先思考!!!!

|||||||||||

|||||||||||

|||||||||||

|||||||||||

|||||||||||

|||||||||||

|||||||||||

答答答答答答答答答答答

案案案案案案案案案案案

往往往往往往往往往往往

下下下下下下下下下下下

翻翻翻翻翻翻翻翻翻翻翻

|||||||||||

|||||||||||

|||||||||||

|||||||||||

|||||||||||

|||||||||||

|||||||||||

class Solution {
    public int kthSmallest(int[][] matrix, int k) {
        int[] target = new int[matrix.length * matrix[0].length];
        int count = 0;
        for(int i = 0 ; i < matrix.length ; i++){
            for(int j = 0 ; j < matrix[i].length ; j++){
                target[count] = matrix[i][j];
                count++;
            }
        }
        Arrays.sort(target);
        return target[k-1];
    }
}

题解:暴力破解法,思路就是遍历二维数组然后存到一个一维数组中,然后对一维数组进行排序,直接返回下标为k-1的数值就行了

class Solution {
    public int kthSmallest(int[][] matrix, int k) {
        // 先确定范围
        int n = matrix.length;
        int l = matrix[0][0];
        int r = matrix[n-1][n-1];
        while(l < r){
            int midder = l + ((r-l) >> 1);
            if(check(matrix, n, k, midder)){
                r = midder;
            }else {
                l = midder + 1;
            }
        }
        return l;
    }

    public boolean check(int matrix[][], int n, int k, int mid){
        // 先从左下角开始,符合条件就往右,不符合就往上计算数量
        int i = n - 1;
        int j = 0;
        int num = 0;
        while (i >= 0 && j < n) {
            if (matrix[i][j] <= mid) {
                num += i + 1;
                j++;
            } else {
                i--;
            }
        }
        return num >= k;
    }
}

题解:二分查找法,简单理解就是我们要找的目标值就是在二维数组的(0,0)(n-1,n-1)之间,此时我们就可以找这个范围数值的中间值,每找一次中间值就要计算一个小于中间值的个数,如果这个中间值不小于k那么右边的r往左移相反L往右移,最终的L就是我们要找的数值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值