[算法]学习笔记day02

注:题目均来自力扣leetcode【学习参考】

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

class Solution {
    public boolean isAnagram(String s, String t) {
        if(s.length() != t.length()) return false;
        int[] count = new int[26];
        
        for(char c : s.toCharArray()){
            count[c - 'a']++;
        }
        
        for(char c : t.toCharArray()){
            count[c - 'a']--;
            if(count[c - 'a'] < 0) return false;
        }
        
        return true;
    }
}

字符串中的第一个唯一字符

案例:

s = “leetcode”
返回 0.

s = “loveleetcode”,
返回 2.

最优

class Solution {
    public int firstUniqChar(String s) {
        int index = -1;
        //反过来,只有26个字符
        for (char ch = 'a'; ch <= 'z'; ch++) {
            int beginIndex = s.indexOf(ch);
            // 从头开始的位置是否等于结束位置,相等说明只有一个,
            if (beginIndex != -1 && beginIndex == s.lastIndexOf(ch)) {
                //取小的,越小代表越前。
				 
                // index = (index == -1 || index > beginIndex) ? beginIndex : index;
                if (index == -1 || index > beginIndex) {
                	index = beginIndex;
                } else {
                	index = index;
                }
            }
        }
        return index;
    }
}
class Solution {
    public int firstUniqChar(String s) {
                char[] chars = s.toCharArray();
        int len = chars.length;
        //定义数组长度为26,表示26个字母   0-25  分别表示a-z的位置
        int[] arr = new int[26];
        int count = 1;
        //遍历字符数组,任何一个字母出现一次,都在arr数组对应位置加1
        for(int i = 0;i<len;i++) {
            arr[chars[i] - 'a'] += count;
        }
        for(int i = 0;i<len;i++) {
            if(arr[chars[i] - 'a'] == 1) return i;
        }
        return -1;
    }
}

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

class Solution {
    public void reverseString(char[] s) {
        //定义一个临时变量,作为中间转换。
        char temp = 0;
        int len = s.length;
        //第1个和最后1个进行交换,第2个和倒数第2个交换,以此类推,交换len/2次。
        for (int i = 0; i < len / 2; i++) {
            temp = s[i];
            s[i] = s[len - i - 1];
            s[len - i - 1] = temp;
        }
    }
}

编写一个函数,以字符串作为输入,反转该字符串中的元音字母。

示例 1:

输入: “hello”
输出: “holle”

双指针的应用

import java.util.*;
class Solution {
    private final static HashSet<Character> set = new HashSet<>(Arrays.asList('a','o','e','i','u','A','O','E','I','U'));
    public String reverseVowels(String s) {
        int i = 0,j = s.length()-1;
        char[] result = new char[s.length()];
        while(i<=j){
            char ci = s.charAt(i);
            char cj =s.charAt(j);
            if(!set.contains(ci)){
                result[i++] = ci;
            }else if(!set.contains(cj)){
                result[j--] = cj;
            }else{
                result[i++] = cj;
                result[j--] = ci;
            }
        }
        return new String(result);
    }
}

最优

class Solution {
    public String reverseVowels(String s) {
       if (s == null || s.trim().equals("")) return s;
        char[] cs = s.toCharArray();
        int low = 0,high = cs.length-1;
        while (low < high) {
            if (isVowelChar(cs[low])) {
                if (isVowelChar(cs[high])) {
                    char temp = cs[low];
                    cs[low] = cs[high];
                    cs[high] = temp;
                    low++;
                    high--;
                } else {
                    high--;
                }
            } else {
                low++;
            }
        }
        return String.valueOf(cs);
    }

给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

示例:

输入:
words = [“oath”,“pea”,“eat”,“rain”] and board =
[
[‘o’,‘a’,‘a’,‘n’],
[‘e’,‘t’,‘a’,‘e’],
[‘i’,‘h’,‘k’,‘r’],
[‘i’,‘f’,‘l’,‘v’]
]

输出: [“eat”,“oath”]

class Solution {
    public List<String> findWords(char[][] board, String[] words) {
        TrieNode tree = TrieNode.buildTree(words);
        List<String> res = new LinkedList<>();
        for(int i = 0; i < board.length; i++) {
            for(int j = 0; j < board[0].length; j++) {
                dfs(i,j,board,tree,res);
            }
        }
        return res;
        
    }
    
    void dfs(int i, int j, char[][] board, TrieNode root, List<String> res) {
        char c = board[i][j];
        if(c=='#') return;
        TrieNode node = root.children[c-'a'];
        if(node==null) return;
        if(node.word!=null) {
            res.add(node.word);
            node.word=null;
        }
        board[i][j]='#';
        if(i+1<board.length) dfs(i+1,j,board,node,res);
        if(i-1>=0) dfs(i-1,j,board,node,res);
        if(j+1<board[0].length) dfs(i,j+1,board,node,res);
        if(j-1>=0) dfs(i,j-1,board,node,res);
        board[i][j]=c;
    }
}

class TrieNode{
    TrieNode[] children = new TrieNode[26];
    String word;
    
    static TrieNode buildTree(String[] words){
        TrieNode root = new TrieNode();
        for(String word : words){
            char[] cs = word.toCharArray();
            root.add(cs, 0);
        }
        return root;
    }
    
    void add(char[] cs, int i){
        if(i==cs.length){
            word = new String(cs);
            return;
        }
        int index = cs[i]-'a';
        if(children[index]==null){
            children[index] = new TrieNode();
        }
        children[index].add(cs,i+1);
    }
}

给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。

示例 1:

输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。

class Solution {
    public int maxProduct(int[] nums) {
        int i = 0;
        int max = Integer.MIN_VALUE;
        int cur = 1;
        while(i<nums.length){
            cur *= nums[i];
            max = cur > max ? cur : max;
            if(cur == 0){
                i++;
                cur = 1;
                continue;
            }
            i++;
        }
        cur = 1;
        i = nums.length - 1;
        while(i>=0){
            cur *= nums[i];
            max = cur > max ? cur : max;
            if(cur == 0){
                i--;
                cur = 1;
                continue;
            }
            i--;
        }
        return max;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值