Java算法题必备知识

本文详细介绍了Java中的基础数据结构和操作,包括数组和字符串的常见操作、动态数组ArrayList的使用、哈希表及其应用、字母异位词分组、最长连续序列算法、栈和队列的实现,以及二叉堆和优先队列的使用,以解决第K个最大元素的问题。
摘要由CSDN通过智能技术生成

1 数组

int m = 5, n = 10;

// 初始化一个大小为 10 的 int 数组
// 其中的值默认初始化为 0
int[] nums = new int[n]

// 初始化一个 m * n 的二维布尔数组
// 其中的元素默认初始化为 false
boolean[][] visited = new boolean[m][n];

2 字符串

2.1 获取字符串的某个字符

String s1 = "hello world";
// 获取 s1[2] 那个字符 l
char c = s1.charAt(2);

2.2 字符串与char数组的互相转化


// 字符串转为char数组
char[] chars = s1.toCharArray();
chars[1] = 'a';
//char数组转为字符串
String s2 = new String(chars);
// 输出:hallo world
System.out.println(s2);

2.3 判断字符串是否相同

// 注意,一定要用 equals 方法判断字符串是否相同
if (s1.equals(s2)) {
    // s1 和 s2 相同
} else {
    // s1 和 s2 不相同
}

2.4 字符串的拼接

// 字符串可以用加号进行拼接
String s3 = s1 + "!";
// 输出:hello world!
System.out.println(s3);

2.5 获取某段字符串

//获取s中[l+1,r)的字符字串
s.substring(l + 1, r)

2.6 去除字符串的某个字符

//去除字符串中的空格
s = s.replaceAll("\\s+", " ");

2.7 去除字符串开头和结尾的空格

s = s.trim();

2.8 将字符串按" "进行划分,最终形成字符串数组

//数组内容为 {i,am,lihao}
String s = "i am lihao";
String[] words = s.split("\\s+");

3.动态数组ArrayList

3.1 ArrayList常用方法

// 判断数组是否为空
boolean isEmpty()

// 返回数组的元素个数
int	size()

// 返回索引 index 的元素
E get(int index)

// 在数组尾部添加元素 e
boolean	add(E e)

4.哈希表

4.1 哈希表的基本操作

// 判断哈希表中是否存在键 key
boolean	containsKey(Object key)

// 获得键 key 对应的值,若 key 不存在,则返回 null
V get(Object key)

// 将 key, value 键值对存入哈希表
V put(K key, V value)

// 如果 key 存在,删除 key 并返回对应的值
V remove(Object key)

4.2 字母异位词分组

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

示例 1:
输入: strs = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]]

示例 2:
输入: strs = [“”]
输出: [[“”]]

示例 3:
输入: strs = [“a”]
输出: [[“a”]]

思路以及代码:
你如何迅速判断两个字符串是异位词,主要考察数据编码和哈希表的使用:
你是否可以找到一种编码方法,使得字母异位词的编码都相同?找到这种编码方式之后,就可以用一个哈希表存储编码相同的所有异位词,得到最终的答案。
我们可以利用ASCLL表,将字符转化为数字,之后建立一个26位存储0/1的数组,字符串存在这个字符就在相应位置设置为1,这样即可完成编码

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String,List<String>> map = new HashMap();
        for(String s:strs){
            String code = encode(s);
            //将编码相同的字符放在一起
            map.putIfAbsent(code,new ArrayList());
            map.get(code).add(s);
        }
        List<List<String>> res = new ArrayList();
        for(List<String> i:map.values()){
            res.add(i);
        }
        return res;
    }

    //将每个字符串输出为一个26位的0/1编码,1表示这个字符串有这个字符
    public String encode(String s){
        char[] count = new char[26];
        for(char c:s.toCharArray()){
            int i = c - 'a';
            count[i]++;
        }
        return new String(count);
    }
}

4.3 最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

示例 2:
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9

思路以及代码:
想找连续序列,首先要找到这个连续序列的开头元素,然后递增,看看之后有多少个元素还在 nums 中,即可得到最长连续序列的长度了。

那么我们可以先把他存在一个set里,之后找到set中不具有i-1元素的哪个i,其中这个i就可能是连续数字的起始元素,之后进行确认即可

class Solution {
    public int longestConsecutive(int[] nums) {
        Set<Integer> set = new HashSet();
        int res = 0;
        for(int i:nums){
            set.add(i);
        }
        for(int i:set){
            //说明i不是第一个
            if(set.contains(i-1)){
                continue;
            }

            int start = i;
            int numlen = 1;

            while(set.contains(start+1)){
                start+=1;
                numlen+=1;
            }
            res = Math.max(res,numlen);
        }
        return res;
    }
}

5.栈和队列

5.1栈和队列的基本操作

// 队列的基本 API
class MyQueue<E> {
    // 向队尾插入元素,时间复杂度 O(1)
    void push(E e);

    // 从队头删除元素,时间复杂度 O(1)
    E pop();

    // 查看队头元素,时间复杂度 O(1)
    E peek();

    // 返回队列中的元素个数,时间复杂度 O(1)
    int size();
}

// 栈的基本 API
class MyStack<E> {
    // 向栈顶插入元素,时间复杂度 O(1)
    void push(E e);

    // 从栈顶删除元素,时间复杂度 O(1)
    E pop();

    // 查看栈顶元素,时间复杂度 O(1)
    E peek();

    // 返回栈中的元素个数,时间复杂度 O(1)
    int size();
}

6.常用数据结构

6.1 二叉堆

其中最长使用的是优先队列,也就是自动排序,以保证每次取出的要么是最大的要么是最小的,具体使用步骤如下:(默认是最小堆)

//初始化
PriorityQueue<ListNode> priorityQueue=new PriorityQueue<>((n1,n2)->  (n2-n1));
//添加元素
priorityQueue.offer(node);
//弹出元素
ListNode node=priorityQueue.poll();
//判空
priorityQueue.isEmpty()
//检索二叉堆头部 为空则返回null
priorityQueue.peek();

6.1.1 数组中的第K个最大元素

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:
输入: [3,2,1,5,6,4], k = 2
输出: 5

示例 2:
输入: [3,2,3,1,2,4,5,5,6], k = 4
输出: 4

思路以及代码:
可以把小顶堆 pq 理解成一个筛子,较大的元素会沉淀下去,较小的元素会浮上来;当堆大小超过 k 的时候,我们就删掉堆顶的元素,因为这些元素比较小,而我们想要的是前 k 个最大元素嘛。

当 nums 中的所有元素都过了一遍之后,筛子里面留下的就是最大的 k 个元素,而堆顶元素是堆中最小的元素,也就是「第 k 个最大的元素」。

class Solution {
    public int findKthLargest(int[] nums, int k) {
        PriorityQueue<Integer> pq = new PriorityQueue();
        for(int i:nums){
            pq.offer(i);
            //堆中元素大于k,就删除堆顶(其实就是把小的都删除了)
            if(pq.size()>k){
                pq.poll();
            }
        }
        //此时,小根堆里面剩的是前k个大的元素
        //堆顶元素最小,也就是数组中第k大的元素了
        return pq.peek();
    }
}
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值