综合篇
前言
本次算法入门训练主要训练以下三个内容:
- 以特殊数据结构为载体的算法结构,比如:数组、链表、栈、二叉树等
- 以考察常见算法思想基础的算法题,比如:动态规划、贪心、回溯等
- 基于某种场景包装下的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两题就是对自身思维的一个考量,以及题目的理解程度,没练过比较难写,不过这是一个不断训练的过程,慢慢来。