常见算法题目:数组(一)

222 阅读1分钟

前言

如果想进大厂工作,除了基础知识,项目经验,还有一些非常重要的能力需要锻炼,其中最重要的就是算法。算法题千千万,但是类型也就几十种,接下来的系列文章,我将面试中常见的算法题类型进行归纳。


数组面试题01. 判定字符是否唯一

实现一个算法,确定一个字符串 s 的所有字符是否全都不同。

示例 1:
输入: s = "leetcode"
输出: false

示例 2:
输入: s = "abc"
输出: true

限制:
0 <= len(s) <= 100
如果你不使用额外的数据结构,会很加分。

代码:
(1)第一种解法

class Solution {
    public boolean isUnique(String astr) {
        String [] arr = astr.split("");
        int count = 0;
        for (int i = 0; i < arr.length; i++) {
            count = 0;
            for (int j = 0; j < arr.length; j++) {
                // 这里有一个小细节,就是比较两个字符是否相等用==,还是equals()
                // ==对于基本数据类型,比较的是它们的值;对于复合数据类型(类、接口、数组),比较的是他们在内存中的存放地址
                // equals方法比较的是字符串的内容是否相同
                // 答案是使用equals()
                if (arr[i].equals(arr[j])) {
                    count++;
                }
                if (count >= 2) {
                    return false;
                }
            }  
        }
        return true;
    }
}

(2)第二种解法 HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合

class Solution {
    public boolean isUnique(String astr) {
        HashSet<Character> hashSet = new HashSet<>();
        for (int i = 0; i < astr.length(); i++) {
            hashSet.add(astr.charAt(i));
        }
        return hashSet.size() == astr.length();
    }
}

数组面试题02. 判定是否互为字符重排

实现一个算法,确定一个字符串 s 的所有字符是否全都不同。

给定两个字符串 s1 和 s2,请编写一个程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。

示例1:
输入: s1 = "abc", s2 = "bca"
输出: true

示例2:
输入: s1 = "abc", s2 = "bad"
输出: false

说明:
0 <= len(s1) <= 100
0 <= len(s2) <= 100


分析

若s1,s2字符串长度不相等,则「不互为重排」;
若 s1,s2某对应字符数量不同,则「不互为重排」;
否则,若s1,s2所有对应字符数量都相同,则「互为重排」;

(1)当s1,s2字符数量相同时,读取s1中的一个字符,然后遍历s2,如果与s1中的该字符相同,则把s2中的这个字符改为"0"
(2)遍历s1中的每一个字符,重复步骤(1)
(3)遍历s2中的"0",如果数量与s2长度相等,则s1,s2互为重排;否则,s1,s2不互为重排


代码

class Solution {
    public boolean CheckPermutation(String s1, String s2) {
        char[] arr1 = s1.toCharArray();
        char[] arr2 = s2.toCharArray();

        if (arr1.length != arr2.length) {
            return false;            
        } else {
            for (int i = 0; i < arr1.length; i++) {
                for (int j = 0; j < arr2.length; j++) {
                    if (arr1[i] == arr2[j]) {
                        arr2[j] = '0';
                        break;
                    }
                }
            }

            int count = 0;
            for (int j = 0; j < arr2.length; j++) {
                if (arr2[j] == '0') {
                    count++;
                } 
            }

            if (count == arr2.length) {
                return true;
            } else {
                return false;
            }

        }

    }
}

数组面试题03. URL化

URL化。编写一种方法,将字符串中的空格全部替换为%20。假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。(注:用Java实现的话,请使用字符数组实现,以便直接在数组上操作。)

示例1:
输入:"Mr John Smith ", 13
输出:"Mr%20John%20Smith"

示例2:
输入:" ", 5
输出:"%20%20%20%20%20"


提示:

字符串长度在 [0, 500000] 范围内。


代码

class Solution {
    public String replaceSpaces(String S, int length) {
        StringBuilder stringBuilder = new StringBuilder();
        // 逐渐遍历字符串
        for (int i = 0; i < length; i++) {
            // 如果不是空格就加入到StringBuilder中,如果是空格
            // 就把"%20"加入到StringBuilder中
            char ch = S.charAt(i);
            if (ch == ' ') {
                stringBuilder.append("%20");
            } else {
                stringBuilder.append(ch);
            }
        }
        return stringBuilder.toString();
    }
}

数组面试题04. 回文排列

给定一个字符串,编写一个函数判定其是否为某个回文串的排列之一。回文串是指正反两个方向都一样的单词或短语。排列是指字母的重新排列。回文串不一定是字典当中的单词。

示例1:
输入:"tactcoa"
输出:true(排列有"tacocat"、"atcocta",等等)

分析:
根据字符串长度,「回文串」可分为两种情况:
「回文串」长度为偶数:所有不同字符的出现次数都为「偶数」;
「回文串」长度为奇数:位于中点的字符出现「奇数」次,其余字符出现「偶数」次;
因此,某字符串是回文串排列之一的「充要条件」为:此字符串中,最多只有一种字符的出现次数为「奇数」,其余所有字符的出现次数都为「偶数」。
考虑使用「哈希表」统计给定字符串中各字符的数量,再根据以上规则判断字符串是否为回文串排列之一。
1638093879-zybntU-ccw-01-04 001 1638093879-LOcrcx-ccw-01-04 009 1638093879-CVFaSD-ccw-01-04 011 1638093879-ZJfyZV-ccw-01-04 014 1638093879-vJEszu-ccw-01-04 015

代码:

class Solution {
    public boolean canPermutePalindrome(String s) {
        // 初始化哈希表
        HashMap<Character, Integer> dic = new HashMap<>();
        // 统计字符串中各字符的数量
        for (int i = 0; i < s.length(); i++) {
            dic.put(s.charAt(i), dic.getOrDefault(s.charAt(i), 0) + 1);
            // getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值。
            // HashMap中key是不可以重复的,如果重复添加的话,HashMap会自动覆盖key一样的数据,保证一个key对应一个value
            // 比如第一次读取到a,则key = a, value = 1;第二次也读取到a,则key = a, value = 2
        }
        int odd = 0;
        for (int val : dic.values()) {
            // 统计“数量为奇数”字符的个数
            if (val % 2 == 1) {    
                // 若“数量为奇数”的字符个数 > 1 ,则不是回文串排列
                if (++odd > 1) // 注意 ++odd > 1 是先执行 odd 自增,再执行逻辑判断; odd++ 的顺序反之
                    return false;
            }
        }
        // 若“数量为奇数”的字符个数 <= 1 ,则是回文串排列
        return true;
    }
}