记录一些算法题 LeetCode上的

本文深入探讨了多个经典编程题目,包括无重复字符的最长子串、最长回文字符串、Z字形变换、三数之和及电话号码的字母组合等。通过详细解析,分享了高效解题思路与技巧,如滑动窗口、回溯算法、双指针法等,旨在提升编程能力和算法理解。

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

//无重复字符的最长子串
//主要思路滑动窗口 遍历字符串不重复的情况时最长子串长度加一当遍历到 重复元素时 从重复元素往后开始计算 并
//与目前最大长度子串比较大小 取最大值

public static int lengthOfLongestSubstring(String s) {
		HashMap<Character, Integer> map = new HashMap<Character, Integer>();
		int max = 0;
		int lef = 0;
		for (int i = 0; i < s.length(); i++) {
			if (map.containsKey(s.charAt(i))) {
				lef = Math.max(lef, map.get(s.charAt(i)) + 1);
			}
			map.put(s.charAt(i), i);
			max = Math.max(max, i - lef + 1);
		}
		return max;
//        if (s.length()==0) return 0;
//        HashMap<Character, Integer> map = new HashMap<Character, Integer>();
//        int max = 0;
//        int left = 0;
//        for(int i = 0; i < s.length(); i ++){
//            if(map.containsKey(s.charAt(i))){
//                left = Math.max(left,map.get(s.charAt(i)) + 1);
//            }
//            map.put(s.charAt(i),i);
//            max = Math.max(max,i-left+1);
//        }
//        return max;
	}

最长回文字符串
找出最长公共子串

public static String longestPalindrome(String s) {
	    if (s.equals(""))
	        return "";
	    String origin = s;
	    String reverse = new StringBuffer(s).reverse().toString();
	    int length = s.length();
	    int[][] arr = new int[length][length];
	    int maxLen = 0;
	    int maxEnd = 0;
	    for (int i = 0; i < length; i++)
	        for (int j = 0; j < length; j++) {
	            if (origin.charAt(i) == reverse.charAt(j)) {
	                if (i == 0 || j == 0) {
	                    arr[i][j] = 1;
	                } else {
	                    arr[i][j] = arr[i - 1][j - 1] + 1;
	                }
	            }

	            if (arr[i][j] > maxLen) {
	                int beforeRev = length - 1 - j;
	                if (beforeRev + arr[i][j] - 1 == i) { 
	                    maxLen = arr[i][j];//记录公共子串的最大长度
	                    maxEnd = i;//记录公共子串最大长度子串的最后一个坐标
	                }
	            }
	        }
	    return s.substring(maxEnd - maxLen + 1, maxEnd + 1);
	}

Z字形变换
我一开始的思路是利用二维数组计算下标这样太麻烦
官方的思路非常巧妙 感觉自己真的是个智障一样 为什么就想不到 代码如下:

public static String convert(String s, int numRows) {
        if (numRows == 1) return s;

        List<StringBuilder> rows = new ArrayList<>();
        for (int i = 0; i < Math.min(numRows, s.length()); i++)
            rows.add(new StringBuilder());

        int curRow = 0;
        boolean goingDown = false;

        for (char c : s.toCharArray()) {
            rows.get(curRow).append(c);
            if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
            curRow += goingDown ? 1 : -1;
        }

        StringBuilder ret = new StringBuilder();
        for (StringBuilder row : rows) ret.append(row);
        return ret.toString();

	}
三数之和
	我自己的代码

	public static List<List<Integer>> threeSum(int[] nums) {
		Long begin = System.currentTimeMillis();
		List<Integer> numbers = new ArrayList<Integer>();
		List<Integer> res = null;
		List<List<Integer>> result = new ArrayList<List<Integer>>();
		int sum = 0;
		for (int i = 0; i < nums.length; i++) {
			numbers.add(nums[i]);
		}
		for (int i = 0; i < nums.length; i++) {
			for (int j = 0; j < nums.length; j++) {
				if (i == j) {
					continue;
				}
				sum = (nums[i] + nums[j]) * -1;
				numbers.remove((Object) nums[i]);
				numbers.remove((Object) nums[j]);
				if (numbers.contains(sum)) {
					res = new ArrayList<Integer>();
					res.add(nums[i]);
					res.add(nums[j]);
					res.add(sum);
					Collections.sort(res);
					if (!result.contains(res)) {
						result.add(res);
					}
				}
				numbers.add(nums[i]);
				numbers.add(nums[j]);
			}
		}
		Long end = System.currentTimeMillis();
		System.out.println(end - begin);
		return result;
	}
	
运行之后再LeetCode上面超时了 一开始卡在了去重的阶段 后利用Collections.sort方法去重,但是随之而来的就是时间复杂度也增加了  因为sort方法里面 还有一层for循环。看完题解 记录一下优化后的结果,先将数组进行排序,利用双指针法。固定一个 指针 其他两个分别从两边相向而行记录满足条件的结果。
public static List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ans = new ArrayList();
        int len = nums.length;
        if(nums == null || len < 3) return ans;
        Arrays.sort(nums); // 排序
        for (int i = 0; i < len ; i++) {
            if(nums[i] > 0) break; // 如果当前数字大于0,则三数之和一定大于0,所以结束循环
            if(i > 0 && nums[i] == nums[i-1]) continue; // 去重
            int L = i+1;
            int R = len-1;
            while(L < R){
                int sum = nums[i] + nums[L] + nums[R];
                if(sum == 0){
                    ans.add(Arrays.asList(nums[i],nums[L],nums[R]));
                    while (L<R && nums[L] == nums[L+1]) L++; // 去重
                    while (L<R && nums[R] == nums[R-1]) R--; // 去重
                    L++;
                    R--;
                }
                else if (sum < 0) L++;
                else if (sum > 0) R--;
            }
        }        
        return ans;
    }
	电话号码的字母组合  用到回溯 这道题 感觉上是遍历树结构的操作 要是数据结构树那里学的比较好的话可能这里应该不是什么很困难的问题
Map<String, String> phone = new HashMap<String, String>() {{
	    put("2", "abc");
	    put("3", "def");
	    put("4", "ghi");
	    put("5", "jkl");
	    put("6", "mno");
	    put("7", "pqrs");
	    put("8", "tuv");
	    put("9", "wxyz");
	  }};
	  
	List<String> output = new ArrayList<String>();
	public void backtrack(String combination, String next_digits) {
	    if (next_digits.length() == 0) {
	      output.add(combination);
	    }else{
	      String digit = next_digits.substring(0, 1);
	      String letters = phone.get(digit);
	      for (int i = 0; i < letters.length(); i++) {
	        String letter = phone.get(digit).substring(i, i + 1);
	        backtrack(combination + letter, next_digits.substring(1));
	      }
	    }
	  }
	  public List<String> letterCombinations(String digits) {
	    if (digits.length() != 0)
	      backtrack("", digits);
	    return output;
	  }	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值