【算法入门级训练】 - DAY7

综合篇



前言

本次算法入门训练主要训练以下三个内容:

  1. 以特殊数据结构为载体的算法结构,比如:数组、链表、栈、二叉树等
  2. 以考察常见算法思想基础的算法题,比如:动态规划、贪心、回溯等
  3. 基于某种场景包装下的1和2

提示:以下是本篇文章正文内容

内容

第一题:连续子数组的最大和

解题思路:一道经典的动态规划题,重点理解动规方程,如果前i-1个元素的最大连续子序列和加上当前元素比当前元素还小,那么前i个元素的最大连续子序列就是当前值,如果大那么就是到加上i值这一段。还有第二种解法用贪心的思想,如果当前值有利于整体的增加那么就加上他,不利于就是他。
OJ链接:第一题

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        //动规
        //定义状态 f(i) : 以下标为i结尾的最大连续子序列的和
        //设置状态转移方程 f(i) = max(f(i-1) + array[i],array[i]) f(i)加上当前元素如果比当前元素还小,那就从当前元素开始
        //初始化状态 f(0) = array[0] max = array[0];
        if (array.length == 0) {
            return 0;
        }
        int[] dp = new int[array.length];
        dp[0] = array[0];
        int max = array[0];
        for(int i = 1; i < array.length; i++){
            dp[i] = Math.max(dp[i-1] + array[i],array[i]);
            if(dp[i] > max){
                max = dp[i];
            }
        }
        return max;
    }
}

第二题:回文数索引

解题思路:定义头尾指针,让两个指针相向而行,如果指针指向的字符相同那么走下一个,如果指向字符不相同,删除掉某个指针指向的字符,如果删掉后是回文串那么这个指针的位置就是你要返回的位置,如果不是那么另一个指针的位置就是你要返回的位置,如果两个指针相遇那么这就是一个回文串。
OJ链接:第二题

import java.util.Scanner;
public class Main {
    public static boolean IsPalindrome(StringBuilder str,int[] start,int[] end){
        //两个指针一个指向开始一个指向结尾
        //向中间靠拢,出现不相等的情况就不是
        int i = 0;
        int j = str.length()-1;
        boolean flg = true;
        while(i <= j){
            if(str.charAt(i) != str.charAt(j)){
                flg = false;
                break;
            }
            i++;
            j--;
        }
        if(start != null){
            start[0] = i;
        }
        if(end != null){
            end[0] = j;
        }
        return flg;
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int num = in.nextInt();
        while(num > 0){
            //使用StringBuilder or StringBuffer 这两个类有删除方法
            StringBuilder str = new StringBuilder(in.next());
            int[] i = new int[1];
            int[] j = new int[1];
            boolean flg = IsPalindrome(str,i,j);
            if(flg){
                System.out.println(-1);
            }else{
                str.deleteCharAt(i[0]);
                if(IsPalindrome(str,null,null)){
                    System.out.println(i[0]);
                }else{
                    System.out.println(j[0]);
                }
            }
            num--;
        }
    }
}

第三题:把数组排成最小的数

解题思路:排序的特殊理解,常见的排序方式都是从大到小或者从小到大,但是这题我们的思路是把数字进行有效序列组合后按字典序排序。
OJ链接:第三题

import java.util.*;

public class Solution {
    public String PrintMinNumber(int [] numbers) {
        if(numbers == null){
            return "";
        }
        ArrayList<Integer> list = new ArrayList<>();
        for(int x : numbers){
            list.add(x);
        }
        Collections.sort(list,new Comparator<Integer>(){
            public int compare(Integer x,Integer y){
                String xs = x + "" + y;
                String ys = y + "" + x;
                return xs.compareTo(ys);
            }
        });
        String str = new String();
        for(Integer x : list){
            str += x;
        }
        return str;
    }
}

第四题:两个链表的第一个公共结点

解题思路:因为我们不确定相交之前两个链表的节点个数是不是相同,如果能确定那么挨个比较即可,理解这个了就很简单了这题
OJ链接:第四题

public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if(pHead1 == null || pHead2 == null){
            return null;
        }
        //求这两个链表的长度
        int length1 = 0;
        int length2 = 0;
        ListNode tmp1 = pHead1;
        ListNode tmp2 = pHead2;
        while(tmp1 != null){
            tmp1 = tmp1.next;
            length1++;
        }
        while(tmp2 != null){
            tmp2 = tmp2.next;
            length2++;
        }
        tmp1 = pHead1;
        tmp2 = pHead2;
        int step = Math.abs(length1 - length2);
        //让长的链表走差值步
        if(length1 > length2){
            for(int i = 0; i < step; i++){
                tmp1 = tmp1.next;
            }
        }else{
            for(int i = 0; i < step; i++){
                tmp2 = tmp2.next;
            }
        }
        //遍历两个链表如果相同就返回
        while(tmp1 != null && tmp2 != null){
            if(tmp1 == tmp2){
                return tmp1;
            }
            tmp1 = tmp1.next;
            tmp2 = tmp2.next;
        }
        return null;
    }
}

总结

以上就是今天训练的内容,今天的2,4两题比较好理解,如果还不理解可能对字符串和链表的结构不是很清楚,需要重新学习一下,1,3两题就是对自身思维的一个考量,以及题目的理解程度,没练过比较难写,不过这是一个不断训练的过程,慢慢来。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值