[算法]学习笔记DAY01

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

关于查找一个数组中只出现一次的数字

根据根据异或运算的定义可知,任何一个数字异或它自己等于0,所以从头到尾异或数组中的每一个数字,那些出现了两次的数字全部在异或中被抵消掉,最终的结果刚好是这个只出现1次的数字。

class Solution {
    public int singleNumber(int[] nums) {
        int re = 0;
        for(int a:nums){
            re ^=  a;
        }
        return re;
    }
}

关于查找一个数组中的众数

这道题用摩尔投票法,设置一个计数器,选定第一个值作为起始值,然后后面的值如果是这个值那么计数加一,如果不等,那么计数减一,当计数器的值为零时,选取当前值作为新值继续计数。因为众数肯定大于1/2所以最后计数器不为零的数肯定是众数。

class Solution {
    public int majorityElement(int[] nums) {
        int result = nums[0];
        int count = 1;
        for(int i=1; i

搜索 m x n 矩阵 matrix 中的一个目标值 target

class Solution {
    public boolean searchMatrix(int[][] a, int target) {
         if (a == null || a.length == 0 || a[0] == null || a[0].length == 0) return false;
        int row = a.length - 1;
        int col = 0;
        int count = 0;
        while(row >= 0 && col < a[0].length) {
            if(target < a[row][col]) row--;
            else if(target > a[row][col]) col++;
            else {count++; row--;col++;}
        }
        return count>0;

    }
}

方法二:二分法

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
    
        for (int i=0; i target){
                    right = mid - 1;
                }else if (matrix[i][mid] < target){
                    left = mid + 1;
                }else {
                    return true;
                }
            }
        }
        return false;
    }
}

给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组

最优方法:写的少,内存耗时都最优

class Solution {
   public void merge(int[] nums1, int m, int[] nums2, int n) {
    int i = m--+--n;
        
    while(n>=0) {
        nums1[i--] = m>=0 && nums1[m]>nums2[n] ? nums1[m--] : nums2[n--];
    }
}
}

比较简介的写法;Arrays.sort大法好

import java.util.Arrays;

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        System.arraycopy(nums2,0,nums1,m,n);
        Arrays.sort(nums1);
    }
}

如果先存储完sum2那么sum1剩下的不用比较 本来就在sum1里面了
先存储完sum1剩下sum2的继续存储sum1里面

class Solution {
	public void merge(int[] nums1, int m, int[] nums2, int n) {
		int  i = m - 1;
		int j = n - 1;
		int k = m + n - 1;
		while(i >=0 && j >= 0) {
			if(nums1[i] > nums2[j]) {
				nums1[k--] = nums1[i--];
			}else {
				nums1[k--] = nums2[j--];
			}
		}
		// 如果j到0,则插入完成
		// 如果j不到0, 则继续插入
        while(j>=0){
			nums1[k--] = nums2[j--];
		}
	}
}

鸡蛋掉落问题

解法一:状态转移求解鸡蛋掉落问题

class Solution {
    public int superEggDrop(int K, int N) {
        int i=1;
        while(g(i,K)

解法二:用O(n)的辅助空间优化时间复杂度 1ms,100%

class Solution {
    public int superEggDrop(int K, int N) {
        int[] res=new int[K];
        Arrays.fill(res,1);
        while (res[K-1]=1;i--){
                res[i]=res[i]+res[i-1]+1;
            }
            res[0]++;
        }
        return res[0];
    }
}

作者:chen-san-tu
链接:https://leetcode-cn.com/problems/two-sum/solution/javaji-dan-diao-luo-wen-ti-by-chen-san-tu/
来源:力扣(LeetCode)

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

class Solution {
    public boolean isPalindrome(String s) {
        int i = 0, j = s.length()-1;
        while(i < j) {
            char pre = s.charAt(i);
            char last = s.charAt(j);
            if(pre >= 'A' && pre <= 'Z') {
                pre += ' ';
            }
            if(last >= 'A' && last <= 'Z') {
                last += ' ';
            }
            if((pre < 'a' || pre > 'z') && (pre < '0' || pre > '9')) {
                i++;
                continue;
            }
            if((last < 'a' || last > 'z') && (last < '0' || last > '9')) {
                j--;
                continue;
            }
            if(pre != last) {
                return false;
            }
            i++;
            j--;
        }
        return true;
    }
}

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串

class Solution {
    public List> partition(String s) {
        // validate
        if (null == s || 0 == s.length()) {
            return new ArrayList<>();
        }
        List> res = new ArrayList<>();
        List temp = new ArrayList<>();
        doPartition(s.toCharArray(),0,res,temp);
        return res;
    }
    
    private void doPartition(char[] chs,int start,List> res,List temp) {
        // base case
        if (start == chs.length) {
            res.add(new ArrayList<>(temp));
            return;
        }
        for (int i = start;i < chs.length;i++) {
            if (isPalindrome(chs,start,i)) {
                temp.add(new String(chs,start,i-start+1));
                doPartition(chs,i+1,res,temp);
                // recover
                temp.remove(temp.size()-1);
            }
        }
    }
    
    private boolean isPalindrome(char[] chs,int start,int end) {
        while (start < end) {
            if (chs[start] == chs[end]) {
                start++;
                end--;
            } else {
                return false;
            }
        }
        return true;
    }
    
}

单词拆分

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

class Solution {
    public boolean wordBreak(String s, List wordDict) {
        if (wordDict.contains(s)) {
            return true;
        }
        Set wordSet = new HashSet<>();
        int len = 0;
        for (String word : wordDict) {
            wordSet.add(word);
            len = Math.max(len, word.length());
        }
        boolean[] dp = new boolean[s.length() + 1];
        dp[0] = true; // wordSet does contain substring(0, 0)
        for (int i = 1; i <= s.length(); i++) {
            for (int j = 1; j <= len; j++) {
                if (i - j >= 0 && dp[i - j] && wordSet.contains(s.substring(i - j, i))) {
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[s.length()];
    }
}

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。

核心就是 DP + DFS

利用 单词划分 的 DP 方法判断是否能够成功划分,能划分则利用 DFS 确定划分情况。

class Solution {
    public List wordBreak(String s, List wordDict) {
        Set set = new HashSet(wordDict);
        List res = new ArrayList();
        int length = s.length();
        boolean[] dp = new boolean[length+1];
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        int len = 0;
        
        for(String tmp : wordDict){
            len = tmp.length();
            if(len > max){
                max = len; 
            }
            if(len < min){
                min = len;
            }
        }
        
        dp[0] = true;
        for(int i = min; i <= length; i++){
            for(int j = i - min; j >= i - max && j >= 0; j--){
                if(dp[j] && set.contains(s.substring(j, i))){
                    dp[i] = true;
                    break;
                }
            }
        }
        
        if(!dp[length]){
            return res;
        }
        
        StringBuilder sb = new StringBuilder();
        dfs(s,set,sb,res,0);
        return res;
        
    }
    
    public void dfs(String s, Set wordDict, StringBuilder sb, List res, int start){
        if(start == s.length()){
            res.add(sb.toString().trim());
            return;
        }

        for(int i=start;i

实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。

示例:

Trie trie = new Trie();

trie.insert(“apple”);
trie.search(“apple”); // 返回 true
trie.search(“app”); // 返回 false
trie.startsWith(“app”); // 返回 true
trie.insert(“app”);
trie.search(“app”); // 返回 true

class Trie {
    private TrieNode root;

    /**
     * Initialize your data structure here.
     */
    public Trie() {
        root = new TrieNode('0');
    }

    /**
     * Inserts a word into the trie.
     */
    public void insert(String word) {
        int length = word.length();
        TrieNode node = root;

        for (int i = 0; i < length; i++) {
            char c = word.charAt(i);
            int position = c - 'a';

            if (node.children[position] == null) {
                node.children[position] = new TrieNode(c);
            }
            node = node.children[position];
        }
        node.children[26] = new TrieNode('0');
    }

    /**
     * Returns if the word is in the trie.
     */
    public boolean search(String word) {
        int length = word.length();
        TrieNode node = root;

        for (int i = 0; i < length; i++) {
            char c = word.charAt(i);
            int position = c - 'a';

            if (node.children[position] == null) {
                return false;
            } else {
                node = node.children[position];
            }
        }

        if (node.children[26] != null) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Returns if there is any word in the trie that starts with the given prefix.
     */
    public boolean startsWith(String prefix) {
        int length = prefix.length();
        TrieNode node = root;

        for (int i = 0; i < length; i++) {
            char c = prefix.charAt(i);
            int position = c - 'a';

            if (node.children[position] == null) {
                return false;
            } else {
                node = node.children[position];
            }
        }
        return true;
    }

    private class TrieNode {
        char val;
        TrieNode[] children;

        public TrieNode(char val) {
            this.val = val;
            children = new TrieNode[27];
        }
    }
}

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * boolean param_2 = obj.search(word);
 * boolean param_3 = obj.startsWith(prefix);
 */

你可能感兴趣的:(算法,数据结构)