文章目录
1、Math
2、String
3、ArrayList
数组排序:
Arrays.sort(int[]);
ArrayList myNumbers = new ArrayList();
方法 | 描述 |
---|---|
add() | 将元素插入到指定位置的 arraylist 中 |
addAll() | 添加集合中的所有元素到 arraylist 中 |
clear() | 删除 arraylist 中的所有元素 |
clone() | 复制一份 arraylist |
contains() | 判断元素是否在 arraylist |
get() | 通过索引值获取 arraylist 中的元素 |
indexOf() | 返回 arraylist 中元素的索引值 |
removeAll() | 删除存在于指定集合中的 arraylist 里的所有元素 |
remove() | 删除 arraylist 里的单个元素 |
size() | 返回 arraylist 里元素数量 |
isEmpty() | 判断 arraylist 是否为空 |
subList() | 截取部分 arraylist 的元素 |
set() | 替换 arraylist 中指定索引的元素 |
sort() | 对 arraylist 元素进行排序 |
toArray() | 将 arraylist 转换为数组 |
ensureCapacity() | 设置指定容量大小的 arraylist |
lastIndexOf() | 返回指定元素在 arraylist 中最后一次出现的位置 |
retainAll() | 保留 arraylist 中在指定集合中也存在的那些元素 |
containsAll() | 查看 arraylist 是否包含指定集合中的所有元素 |
replaceAll() | 将给定的操作内容替换掉数组中每一个元素 |
removeIf() | 删除所有满足特定条件的 arraylist 元素 |
forEach() | 遍历 arraylist 中每一个元素并执行特定操作 |
intervals.sort(new Comparator<Interval>(){
@Override
public int compare(Interval a, Interval b){
return a.start - b.start;
}
});
4、Stack
import java.util.*;
序号 | 方法描述 |
---|---|
1 | boolean empty() 测试堆栈是否为空。 |
2 | Object peek( ) 查看堆栈顶部的对象,但不从堆栈中移除它。 |
3 | Object pop( ) 移除堆栈顶部的对象,并作为此函数的值返回该对象。 |
4 | Object push(Object element) 把项压入堆栈顶部。 |
5 | int search(Object element) 返回对象在堆栈中的位置,以 1 为基数。 |
4、Queue
import java.util.LinkedList;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
//add()和remove()方法在失败的时候会抛出异常(不推荐)
Queue<String> queue = new LinkedList<String>();
//添加元素
queue.offer("a");
queue.offer("b");
queue.offer("c");
queue.offer("d");
queue.offer("e");
for(String q : queue){
System.out.println(q);
}
System.out.println("===");
System.out.println("poll="+queue.poll()); //返回第一个元素,并在队列中删除
for(String q : queue){
System.out.println(q);
}
System.out.println("===");
System.out.println("peek="+queue.peek()); //返回第一个元素
for(String q : queue){
System.out.println(q);
}
}
}
4、HashMap
// 引入 HashMap 类
import java.util.HashMap;
public class RunoobTest {
public static void main(String[] args) {
// 创建 HashMap 对象 Sites
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
// 添加键值对
Sites.put(1, "Google");
Sites.put(2, "Runoob");
Sites.put(3, "Taobao");
Sites.put(4, "Zhihu");
// 输出 key 和 value
for (Integer i : Sites.keySet()) {
System.out.println("key: " + i + " value: " + Sites.get(i));
}
// 返回所有 value 值
for(String value: Sites.values()) {
// 输出每一个value
System.out.print(value + ", ");
}
}
}
方法 | 描述 |
---|---|
clear() | 删除 hashMap 中的所有键/值对 |
clone() | 复制一份 hashMap |
isEmpty() | 判断 hashMap 是否为空 |
size() | 计算 hashMap 中键/值对的数量 |
put() | 将键/值对添加到 hashMap 中 |
putAll() | 将所有键/值对添加到 hashMap 中 |
putIfAbsent() | 如果 hashMap 中不存在指定的键,则将指定的键/值对插入到 hashMap 中。 |
remove() | 删除 hashMap 中指定键 key 的映射关系 |
containsKey() | 检查 hashMap 中是否存在指定的 key 对应的映射关系。 |
containsValue() | 检查 hashMap 中是否存在指定的 value 对应的映射关系。 |
replace() | 替换 hashMap 中是指定的 key 对应的 value。 |
replaceAll() | 将 hashMap 中的所有映射关系替换成给定的函数所执行的结果。 |
get() | 获取指定 key 对应对 value |
getOrDefault() | 获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值 |
forEach() | 对 hashMap 中的每个映射执行指定的操作。 |
entrySet() | 返回 hashMap 中所有映射项的集合集合视图。 |
keySet() | 返回 hashMap 中所有 key 组成的集合视图。 |
values() | 返回 hashMap 中存在的所有 value 值。 |
merge() | 添加键值对到 hashMap 中 |
compute() | 对 hashMap 中指定 key 的值进行重新计算 |
computeIfAbsent() | 对 hashMap 中指定 key 的值进行重新计算,如果不存在这个 key,则添加到 hasMap 中 |
computeIfPresent() | 对 hashMap 中指定 key 的值进行重新计算,前提是该 key 存在于 hashMap 中。 |
5、华为机试
(1)模板
import java.util.*;
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
int len;
while((str = br.readLine()) != null){
len = Integer.parseInt(br.readLine());
System.out.println(str.substring(0, len));
}
}
}
常考算法
☘️字符串
1、最长回文数
import java.util.*;
public class Solution {
public int getLongestPalindrome(String A, int n) {
// write code here
int maxL = 0;
for(int i = 0; i < (n - 1) * 2; i++){
int left = (int)Math.floor(i * 0.5);
int right = (int)Math.ceil(0.5 * i);
while(left >= 0 && right <= n-1 && A.charAt(left) == A.charAt(right)){
left--;
right++;
}
maxL = right - left - 1 > maxL ? right - left - 1 : maxL;
}
return maxL;
}
}
2、接雨水(NC128)
class Solution {
public int trap(int[] height) {
int left = 0;
int right = height.length - 1;
int maxLeftHeight = 0;
int maxrightHeight = 0;
int result = 0;
while(left < right){
if(height[left] <= height[right]){
maxLeftHeight = Math.max(maxLeftHeight, height[left]);
result += maxLeftHeight - height[left];
left++;
}else{
maxrightHeight = Math.max(maxrightHeight, height[right]);
result += maxrightHeight - height[right];
right--;
}
}
return result;
}
}
6、括号匹配(NC52)
import java.util.*;
public class Solution {
/**
* @param s string字符串
* @return bool布尔型
*/
public boolean isValid (String s) {
// write code here
Stack<Character> st = new Stack<Character>();
for(char item : s.toCharArray()){
if(item == '(')
st.push(')');
else if(item == '[')
st.push(']');
else if(item == '{')
st.push('}');
else if(st.empty() || st.pop() != item)
return false;
}
return st.empty();
}
}
7、回文数字(NC56)
import java.util.*;
public class Solution {
/**
* 在不使用额外的内存空间的条件下判断一个整数是否是回文数字
* @param x int整型
* @return bool布尔型
*/
public boolean isPalindrome (int x) {
// write code here
if(x < 0) return false;
int y = 0, temp = x;
while(temp != 0){
y = y *10 + temp % 10;
temp = temp / 10;
}
return y == x;
}
}
最长重复子串(NC142)
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
定义重复字符串是由两个相同的字符串首尾拼接而成,例如abcabc便是长度为6的一个重复字符串,而abcab则不存在重复字符串。
给定一个字符串,请返回其最长重复子串的长度。
若不存在任何重复字符子串,则返回 0 。
* @param a string字符串 待计算字符串
* @return int整型
*/
public int solve (String a) {
// write code here
int maxL = 0;
for(int j = 0; j < a.length() - 1; j++){
int left = (int) Math.floor(j + 0.5);
int right = (int) Math.ceil(j + 0.5);
for(int i = maxL + 1; left + i <= a.length() - 1 && right - i >= 0; i++){
int left2 = right - i;
int right2 = right;
while(left2 < right && right2 <= a.length() - 1){
if(a.charAt(left2) == a.charAt(right2)){
left2++;
right2++;
}else{
break;
}
}
if(left2 == right)
maxL = i;
}
}
return maxL * 2;
}
}
字符串全排列(JZ27)
import java.util.ArrayList;
public class Solution {
public ArrayList<String> resultList = new ArrayList<>();
public void func(StringBuilder resultStr, StringBuilder targetStr){
if(targetStr.length() == 0 && !resultList.contains(resultStr.toString())){
resultList.add(resultStr.toString());
return ;
}
for(int i = 0; i < targetStr.length(); i++){
StringBuilder tempa = new StringBuilder(resultStr);
StringBuilder tempb = new StringBuilder(targetStr);
tempa.append(targetStr.charAt(i));
tempb.deleteCharAt(i);
func(tempa, tempb);
}
return ;
}
public ArrayList<String> Permutation(String str) {
func(new StringBuilder(str.length()), new StringBuilder(str));
return resultList;
}
}
统计1到n中1出现的个数(JZ31)
![](https://i-blog.csdnimg.cn/blog_migrate/60cef3f1b192c5cdb426825f1f03e011.png)
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
int count = 0, digit = 1;
int heigh = n / 10, cur = n % 10, low = 0;
while(heigh != 0 || cur != 0){
if(cur == 0) count += heigh * digit;
else if(cur == 1) count += heigh * digit + low + 1;
else count += heigh *digit + digit;
low += cur * digit;
cur = heigh % 10;
heigh /= 10;
digit *= 10;
}
return count;
}
}
🔗链表
判断链表是否有环(NC4)
/**
* 快慢指针的解法, 一个指针走两步 一个指针走一步,如果快指针直接到了null 说明没有环, 如果有环的话 总有一次结果会让快指针和慢指针相等。
*/
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode lowPoint = head;
ListNode fastPoint = head;
while(fastPoint != null && fastPoint.next != null){
lowPoint = lowPoint.next;
fastPoint = fastPoint.next.next;
if(lowPoint == fastPoint)
return true;
}
return false;
}
}
链表内指定区间反转(NC21)
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
public ListNode reverseBetween (ListNode head, int m, int n) {
// write code here
if(head == null) return null;
ListNode res = new ListNode(-1);
res.next = head; // -1->1->2->3->4->5
ListNode pre = res; //备份指针
//移动指针,找到m之前的位置
for(int i = 1; i<m; i++){
pre = pre.next; //指向1
}
//创建当前指针
ListNode cur = pre.next; //指向2
//反转链表,从m这个位置开始到n
for(int i = m; i < n; i++){
ListNode temp = cur.next;
cur.next = temp.next;
temp.next = pre.next;
pre.next = temp;
}
return res.next;
}
}
链表排序(NC70)
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode类 the head node
* @return ListNode类
*/
public ListNode sortInList (ListNode head) {
// write code here
ListNode firstPoint = null;
ListNode secondePoint;
// 使用冒泡排序,只对其中的数据部分进行交换
while(firstPoint != head.next){
secondePoint = head;
while(secondePoint.next != firstPoint){
if(secondePoint.val > secondePoint.next.val){
int temp = secondePoint.val;
secondePoint.val = secondePoint.next.val;
secondePoint.next.val = temp;
}
secondePoint = secondePoint.next;
}
firstPoint = secondePoint;
}
return head;
}
}
合并两个有序链表(NC33)
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
* @param l1 ListNode类
* @param l2 ListNode类
* @return ListNode类
*/
public ListNode mergeTwoLists (ListNode l1, ListNode l2) {
// write code here
if(l1 == null) return l2;
if(l2 == null) return l1;
ListNode l0 = new ListNode(0); // 额外增加一个新节点
ListNode p = l0;
while(l1 != null && l2 != null){
if(l1.val > l2.val){
p.next = l2;
l2 = l2.next;
}else{
p.next = l1;
l1 = l1.next;
}
p = p.next;
}
if(l1 != null)
p.next = l1;
if(l2 != null)
p.next = l2;
return l0.next;
}
}
两个链表相加(NC40)
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head1 ListNode类
* @param head2 ListNode类
* @return ListNode类
*/
public ListNode addInList (ListNode head1, ListNode head2) {
// write code here
if(head1 == null) return head2;
if(head2 == null) return head1;
head1 = reverseList(head1);
head2 = reverseList(head2);
int jinWei = 0; // 进位标识符
int sum;
ListNode resultList = new ListNode(0); // 增加一个空白节点,方便插入
ListNode p = resultList; // 空白链表的指针方便往后移动
while(head1 != null || head2 != null){
sum = jinWei;
ListNode tempNode = head1; // 将两个数的余数,存放在之前的节点中(不额外生成节点,默认是链表1中的节点)
if(head1 != null){
sum += head1.val;
head1 = head1.next;
}
if(head2 != null){
sum += head2.val;
tempNode = head2;
head2 = head2.next;
}
tempNode.val = sum % 10;
jinWei = sum / 10;
p.next = tempNode;
p = p.next;
}
// 如果两个链表遍历完了,还有进位,就为其新生成一个节点,插入进去
if(jinWei == 1) p.next = new ListNode(1);
return reverseList(resultList.next);
}
/**
* 链表反转
*/
public ListNode reverseList(ListNode l){
ListNode p = l.next;
l.next = null;
while(p != null){
ListNode temp = p;
p = p.next;
temp.next = l;
l = temp;
}
return l;
}
}
删除链表的倒数第n个节点(NC53)
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode类
* @param n int整型
* @return ListNode类
*/
public ListNode removeNthFromEnd (ListNode head, int n) {
// write code here
ListNode resultNode = new ListNode(0);
resultNode.next = head;
ListNode firstPoint = resultNode;
ListNode seconedPoint = resultNode;
for(int i = 0; i <= n; i++)
firstPoint = firstPoint.next;
while(firstPoint != null){
firstPoint = firstPoint.next;
seconedPoint = seconedPoint.next;
}
seconedPoint.next = seconedPoint.next.next;
return resultNode.next;
}
}
重排链表(NC2)
import java.util.*;
/**
输入:{1,2,3,4}
返回值:{1,4,2,3}
说明:给定head链表1->2->3->4, 重新排列为 1->4->2->3,会取head链表里面的值打印输出
输入:{1,2,3,4,5}
返回值:{1,5,2,4,3}
说明:给定head链表1->2->3->4->5, 重新排列为 1->5>2->4->3,会取head链表里面的值打印输出
*/
public class Solution {
public void reorderList(ListNode head) {
ListNode lowPoint = head, fastPoint = head;
Stack stack = new Stack();
if(fastPoint == null || fastPoint.next == null || fastPoint.next.next == null) return ;
// 找中间点
while(fastPoint.next != null && fastPoint.next.next != null){
fastPoint = fastPoint.next.next;
lowPoint = lowPoint.next;
}
// 后半段入栈
ListNode secondPoint = lowPoint.next;
lowPoint.next = null;
while(secondPoint != null){
stack.push(secondPoint);
secondPoint = secondPoint.next;
}
// 插入操作
ListNode firstPoint = head;
while(!stack.empty() && firstPoint != null){
ListNode popPoint = (ListNode) stack.pop();
popPoint.next = firstPoint.next;
firstPoint.next = popPoint;
firstPoint = firstPoint.next.next;
}
}
}
大数加法(NC1)
原理都是遍历两个字符串或者链表,和上题类似
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 计算两个数之和
* @param s string字符串 表示第一个整数
* @param t string字符串 表示第二个整数
* @return string字符串
*/
public String solve (String s, String t) {
// write code here
int sL = s.length() - 1;
int tL = t.length() - 1;
StringBuilder resultStr = new StringBuilder(Math.max(sL, tL) + 1);
int jinWei = 0;
int sum;
while(sL >= 0 || tL >= 0){
sum = jinWei;
if(sL >= 0){
sum += s.charAt(sL) - '0';
sL--;
}
if(tL >= 0){
sum += t.charAt(tL) - '0';
tL--;
}
resultStr.append((sum % 10) + "");
jinWei = sum / 10;
}
if(jinWei == 1) resultStr.append("1");
return resultStr.reverse().toString();
}
}
寻找第K大(NC88)
import java.util.*;
public class Solution {
// 传统的 partition 算法
public int patition(int[] a, int left, int right, int K){
if(left > right)
return -1;
int leftPoint = left;
int rightPoint = right;
int shaoBing = a[leftPoint];
while(leftPoint < rightPoint){
while(leftPoint < rightPoint && a[rightPoint] >= shaoBing)
rightPoint--;
a[leftPoint] = a[rightPoint];
while(leftPoint < rightPoint && a[leftPoint] <= shaoBing)
leftPoint++;
a[rightPoint] = a[leftPoint];
}
a[leftPoint] = shaoBing;
if(leftPoint == K) return a[leftPoint];
else if (leftPoint > K) return patition(a, left, leftPoint - 1, K);
else return patition(a, leftPoint + 1, right, K);
}
public int findKth(int[] a, int n, int K) {
// 转化为求解升序数组中,排在第n-k的数
return patition(a, 0, n-1,n-K);
}
}
🍂栈
栈的压入、弹出序列(JZ21)
import java.util.*;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
Stack<Integer> sta = new Stack<>();
int pushAPoint = 0;
int popAPoint = 0;
while(pushAPoint < pushA.length && popAPoint < popA.length){
sta.push(pushA[pushAPoint]);
pushAPoint++;
while(!sta.isEmpty() && sta.peek() == popA[popAPoint]){
sta.pop();
popAPoint++;
}
}
if(sta.isEmpty())
return true;
return false;
}
}
🍀 树
判断一棵二叉树是否为搜索二叉树和完全二叉树(NC60)
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类 the root
* @return bool布尔型一维数组
*/
int pre = Integer.MIN_VALUE;
// 是否为搜索树
public boolean dfs(TreeNode root){
if(root == null) return true;
if(!dfs(root.left)) return false;
if(root.val <= pre) return false;
pre = root.val;
return dfs(root.right);
}
// 是否为完全二叉树
private boolean judgeTotalTree(TreeNode root) {
if (root == null) {
return true;
}
Queue<TreeNode> queue = new LinkedList<>();
TreeNode p = root;
queue.offer(p);
boolean reachEnd = false;
while (!queue.isEmpty()) {
p = queue.poll();
if (reachEnd && p != null) {
return false;
}
if (p == null) {
reachEnd = true;
continue;
}
queue.offer(p.left);
queue.offer(p.right);
}
return true;
}
public boolean[] judgeIt (TreeNode root) {
// write code here
boolean[] result = new boolean[]{dfs(root),judgeTotalTree(root)};
return result;
}
}
求二叉树的层序遍历(NC15)
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类
* @return int整型ArrayList<ArrayList<>>
*/
public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
// write code here
if(root == null)
return new ArrayList<>();
Queue<TreeNode> q = new LinkedList<TreeNode>();
ArrayList<ArrayList<Integer>> resultList = new ArrayList<>();
ArrayList<Integer> tempList = new ArrayList<>();
TreeNode flage = null;
q.offer(root);
q.offer(flage);
while(!q.isEmpty()){
TreeNode t = q.poll();
if(t != null){
if (t.left != null ) q.offer(t.left);
if (t.right != null ) q.offer(t.right);
tempList.add(t.val);
}else{
resultList.add(new ArrayList<>(tempList));
if(q.isEmpty()) break;
q.offer(t);
tempList.clear();
}
}
return resultList;
}
}
判断二叉树是否对称(NC16)
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类
* @return bool布尔型
*/
public boolean isSymmetric (TreeNode root) {
// write code here
if(root == null)
return true;
return isCheck(root.left, root.right);
}
public boolean isCheck(TreeNode left, TreeNode right){
if(left == null && right == null)
return true;
if(left == null || right == null)
return false;
return left.val == right.val && isCheck(left.left, right.right) && isCheck(left.right, right.left);
}
}
最长公共前缀(NC55)
import java.util.*;
public class Solution {
/**
*
* @param strs string字符串一维数组
* @return string字符串
*/
public String longestCommonPrefix (String[] strs) {
// write code here
if(strs.length == 0)
return "";
int L = 0;
for(int i = 0; i < strs[0].length(); i++){
Character c = strs[0].charAt(i);
for(int j = 0; j < strs.length; j ++){
if(strs[j].length() <= i || strs[j].charAt(i) != c)
return strs[0].substring(0, L);
}
L++;
}
return strs[0].substring(0, L);
}
}
买卖股票的最好时机
import java.util.*;
public class Solution {
/**
* @param prices int整型一维数组
* @return int整型
*/
public int maxProfit (int[] prices) {
// write code here
int max = 0;
int currentmax = 0;
for(int i = 1; i < prices.length; i++){
currentmax += prices[i] - prices[i - 1];
if(currentmax < 0)
currentmax = 0;
else
max = max > currentmax ? max : currentmax;
}
return max;
}
}
🔡矩阵数组
圆圈中最后剩下的数(JZ46)
/*
让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
*/
import java.util.*;
public class Solution {
public int LastRemaining_Solution(int n, int m) {
if(n==0) return -1;
if(n==1) return 1;
int index=0;
for(int i=2; i<=n;++i)
{
index = (index+m)%i;
}
return index;
}
}
数组中出现次数超过一般的数字(NC73)
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
int a = -1, b = 0;
for(int i = 0; i < array.length; i++){
if(a == -1){
a = array[i];
b++;
}else if(a == array[i]){
b++;
}else if(a != array[i]){
b--;
if(b == 0) a = -1;
}
}
return a;
}
}
数组中相加和为0的三元组(NC54)
import java.util.*;
/**
* @author dyl
* @description: 先排序,固定一个数,用双指针寻找两个数,重要的是两个指针移动的时机。
* @date 2021/8/2 0002 上午 11:04
*/
public class Solution {
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
Arrays.sort(num);
for(int i = 0; i < num.length; i++){
int j = i + 1, j2 = num.length - 1;
while(j < j2){
if(-num[i] == num[j] + num[j2]){
ArrayList<Integer> tempList = new ArrayList<>();
tempList.add(num[i]);
tempList.add(num[j]);
tempList.add(num[j2]);
Collections.sort(tempList);
if (!result.contains(tempList)){
result.add(tempList);
}
j++;
}else if(-num[i] > num[j] + num[j2]){
j++;
}else if(-num[i] < num[j] + num[j2]){
j2--;
}
}
}
return result;
}
}
**矩阵的最小路径和(**NC59)
import java.util.*;
public class Solution {
/**
*
* @param matrix int整型二维数组 the matrix
* @return int整型
* 在原数组上修改,所以几乎不增加什么额外内存
*/
public int minPathSum (int[][] matrix) {
// write code here
int i, j;
int w = matrix[0].length, h = matrix.length;
for(i = 0; i < h; i++){
for(j = 0; j < w; j++){
if(i == 0 && j != 0)
matrix[i][j] += matrix[i][j - 1];
else if(i != 0 && j == 0)
matrix[i][j] += matrix[i - 1][j];
else if(i != 0 && j != 0)
matrix[i][j] += Math.min(matrix[i - 1][j], matrix[i][j - 1]);
}
// System.out.println(Arrays.toString(matrix[i]));
}
return matrix[h - 1][w - 1];
}
}
螺旋矩阵(NC38)/顺时针打印(JZ19)
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printMatrix(int [][] matrix) {
ArrayList<Integer> result = new ArrayList<>();
int top = 0, bottom = matrix.length - 1;
int left = 0, right = matrix[0].length - 1;
while(top <= bottom && left <= right){
for(int i = left; i <= right; i++)
result.add(matrix[top][i]);
top++;
for(int i = top; i <= bottom; i++)
result.add(matrix[i][right]);
right--;
for(int i = right; i >= left && top - 1 != bottom; i--)
result.add(matrix[bottom][i]);
bottom--;
for(int i = bottom; i >= top && left != right + 1; i--)
result.add(matrix[i][left]);
left++;
}
return result;
}
}
合并区间(NC37)
import java.util.*;
/**
* Definition for an interval.
给出一组区间,请合并所有重叠的区间。
请保证合并后的区间按区间起点升序排列。
输入:[[10,30],[20,60],[80,100],[150,180]]
返回值:[[10,60],[80,100],[150,180]]
* public class Interval {
* int start;
* int end;
* Interval() { start = 0; end = 0; }
* Interval(int s, int e) { start = s; end = e; }
* }
*/
public class Solution {
public ArrayList<Interval> merge(ArrayList<Interval> intervals) {
int L = intervals.size();
if(L == 0) return intervals;
intervals.sort(new Comparator<Interval>(){
@Override
public int compare(Interval a, Interval b){
return a.start - b.start;
}
});
ArrayList<Interval> result = new ArrayList<Interval>();
for(int i = 1; i < L; i++){
if(intervals.get(i).start <= intervals.get(i - 1).end){
intervals.get(i).start = Math.min(intervals.get(i - 1).start, intervals.get(i).start);
intervals.get(i).end = Math.max(intervals.get(i - 1).end, intervals.get(i).end);
}else{
result.add(intervals.get(i - 1));
}
}
result.add(L - 1));
return result;
}
}
🍁动态规划
青蛙跳台阶(NC68)
/**
题目分析,假设f[i]表示在第i个台阶上可能的方法数。逆向思维。如果我从第n个台阶进行下台阶,下一步有2中可能,一种走到第n-1个台阶,一种是走到第n-2个台阶。所以f[n] = f[n-1] + f[n-2].
那么初始条件了,f[0] = f[1] = 1。
所以就变成了:f[n] = f[n-1] + f[n-2], 初始值f[0]=1, f[1]=1,目标求f[n]
*/
public class Solution {
int result = 0;
public int jumpFloor(int target) {
if(target == 0 || target == 1) return target;
int a = 1, b = 1, c;
for(int i = 2; i <= target; i++){
c = a + b;
a = b;
b = c;
}
return b;
}
}
// if(target - 1 > 0)
// jumpFloor(target - 1);
// else if(target - 1 == 0)
// result++;
// if(target - 2 > 0)
// jumpFloor(target - 2);
// else if(target - 2 == 0)
// result++;
// return result;
二分查找-II(NC105)
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 如果目标值存在返回下标,否则返回 -1
* @param nums int整型一维数组
* @param target int整型
* @return int整型
*/
public int search (int[] nums, int target) {
// write code here
return serch2(0, nums.length - 1, nums, target );
}
public int serch2(int left, int right, int[] nums, int target){
if(left > right)
return -1;
int mind = (int)((left + right) / 2);
if(nums[mind] > target)
return serch2(left, mind - 1, nums, target );
else if(nums[mind] < target)
return serch2(mind + 1, right, nums, target );
else{
int firstIndex = mind;
// 往前找第一个位置
while(firstIndex >= 0 && nums[mind] == nums[firstIndex]){
firstIndex--;
}
return firstIndex + 1;
}
}
}
二进制中1的个数(NC120)
public class Solution {
public int NumberOf1(int n) {
int count = 0;
while(n != 0){
count += n & 1;
n = n >>> 1;
}
return count;
}
最大公约数(NC151)
更相减损术
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 更相减损术的做法如下:
119-85=34 85-34=51 51-34=17 34-17=17
* 求出a、b的最大公约数。
* @param a int
* @param b int
* @return int
*/
public int gcd (int a, int b) {
// write code here
while(a != b){
if(a > b)
a -= b;
else
b -= a;
}
return a;
}
}
打家劫舍问题,不相邻最大子序列和(NC144)
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
输入:4,[4,2,3,5]
返回值:9
说明:其中[4,5]的选取方案是在满足不同时选取相邻位置的数的情况下是最优的答案
其实就是一个打家劫舍的问题,数组中每一个元素值就是可以偷的金额,相邻的不能偷,求能够偷出的最大金额是多少。
设置一个状态转移数组dp,dp[i]表示数组中前i个元素所能偷的最大金额是多少
状态转移表达式:
(1)对于当前的元素arr[i],如果偷,那么dp[i] = dp[i-2] + arr[i]
(2)如果不偷,那么dp[i] = dp[i-1]
* @param n int整型 数组的长度
* @param array int整型一维数组 长度为n的数组
* @return long长整型
*/
public long subsequence (int n, int[] array) {
// write code here
int[] dp = new int[n + 1];
dp[0] = 0;
dp[1] = array[0];
for(int i = 2; i <= n; i++){
dp[i] = Math.max(dp[i - 1], dp[i - 2] + array[i-1]);
}
return dp[n];
}
}
大疆无人机
移动的最短用时
题目描述:
最近DJI发布了一款Robomaster S1机器人,小伙伴们都沉迷其中不能自拔。小J为了能够在竞速比赛中迅速获胜,他决定利用开发的优势,在里面植入
一套最优化的寻路算法。
比赛规则如下: 在比赛场地内预先设置N个路标,路标编号从0到N-1,S1只能沿直线在两个有连接的路标之间移动(部分路标之间是没有连接的) 比赛
场地内的S1机器人从编号为0的路标出发,然后裁判给出随机一个路标(从0到N-1号路标中随机挑选一个)作为终点路标,要求S1机器人以尽可能快的速
度从0号路标达到终点路标,总路程用时最短者获胜。
裁判会确保从0号路标和随机挑选的终点路标之间肯定存在至少一条路径。 小J在比赛开始前就已经得知了路标的数量 、通道的数量(每两个可以直接连接
的路标点为一个通道)以及小车在每个通道上移动需要的时间。他需要编写一套算法,以确保能够快速找到最短路径,并输出小车在该路径移动所需要的时
间,你能帮他实现这套算法吗?
输入描述
第一行输入两个个正整数 N和 P,其中N表示路标的数量, P表示通道的数量。 (1 < N <= 200, 0 <= P <= N * (N - 1) / 2 )
接下来的P行,每行输入三个正整数 A, B, T,A表示起点路标的编号,B表示终点路标的编号,T表示路标A到路标B需要时间T。 (0 <= A, B <= N-1, 1 <= T <= 100)
最后一行输入一个正整数 X,表示裁判给出的终点路标编号 (0 =< X <= N)
输出描述
输出一个正整数,表示小车从0号路标到X号路标之间移动的最短用时
样例输入
4 5
0 1 15
1 2 15
0 3 50
1 3 30
2 3 10
3
package com.ljn.test;
import java.util.Scanner;
public class Test4 {
//最短路径值
static int min = Integer.MAX_VALUE;
//二维数组记录路径值。如:1到2路径3 就是int[1][2]=3
static int[][] edge = new int[100][100];
//普通数组记录该点是否已走过 0-未经过 1-已经过
static int[] vertex = new int[100];
//n-站点数 ,m-路线数 ,endPoint-终点编号
static int n, m,endPoint;
static Scanner input = new Scanner(System.in);
public static void main(String[] args) {
//输入的第一行第一个数字-站点数
n = input.nextInt();
//输入的第一行第二个数字-路线数
m = input.nextInt();
//外层循环-站点数
for (int i = 0; i < n; i++) {
//内层循环-线路数
for (int j = 1; j <= m; j++) {
//如果相等就相当于 1站点到1站点,无意义 置为0
if (i == j) {
edge[i][j] = 0;
} else {
//路径默认值设为最大值
edge[i][j] = Integer.MAX_VALUE;
}
}
}
//根据线路数m 循环遍历 把路径值赋给初始化好的二维数组
for (int i = 0; i < m; i++) {
int a = input.nextInt();
int b = input.nextInt();
int c = input.nextInt();
edge[a][b] = c;
}
//输入的最后一行是 要计算的终点站
endPoint = input.nextInt();
dfs(0, 0);
System.out.println(min);
}
/**
*
* @param cur 当前站点
* @param dis 目前走过的距离
*/
public static void dfs(int cur, int dis) {
/**
* 如果当前路径大于之前找到的最小值,可直接返回
* */
if (dis > min) {
return;
}
/**
* 判断是否达到终点,更新最小值,返回
* */
if(cur == endPoint) {
if (dis < min) {
min = dis;
return;
}
}
/**
* 当前点到其他各点之间可连通但是还未添加进来时,遍历执行
* */
for (int i = 1; i <= n; i++) {
if (edge[cur][i] != Integer.MAX_VALUE && vertex[i] == 0) {
vertex[i] = 1;
dfs(i, dis+edge[cur][i]);
/**
* 回溯
**/
vertex[i] = 0;
}
}
return;
}
}
游戏王背包问题
题目描述:
有许多程序员都热爱玩游戏,而小J自称为游戏王,曾玩过几百种游戏,几乎所有能玩到的游戏大作都玩遍了。随着时间的推移,他发觉已经没有游戏
可以让他玩了!于是他想改玩一些古老的游戏,以成为真正的“游戏王”。他希望在接下来的一段时间内将过去出的游戏全部玩一遍,但是毕竟时间有限
,因此他感到很苦恼。于是他想到一个计划,他先将每个游戏标上一个成就值,同时对每个游戏都估算一个通关所需要的天数,他计划在未来X天内
让自己玩游戏的成就达到最大,那么他应该怎么做计划呢?(假设每个游戏最多只计划玩一遍,而且每个游戏必须玩完通关才能取得成就值,且通关每
个游戏最小时间单位是1天)
输入描述
第一行输入两个整数N和X,中间用空格隔开,其中N表示游戏的数目N(1<=N<=10),X表示计划玩游戏的总时间天数 (1<=X<=1000)。
第二行输入第1个游戏的成就值A1(0<=A1<=10000) 和 通关所需要花费时间B1天 (1<=Bi<=500) 中间用空格隔开。
第N+1行输入第N游戏的成就值An(0<=An<=10000) 和 通关所需要花费时间Bn天(1<=Bn<=500) 中间用空格隔开
输出描述
可以达到成就之和的最大值。
样例输入
2 2
10 1
20 2
样例输出
20
提示
输入样例二:
3 4
10 2
18 3
10 2
输出样例二:
20
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();//数量
int x = scan.nextInt();//上限
int[] w = new int[n+1];
int[] v = new int [n+1];
for (int i = 1; i <= n; i++) {
w[i] = scan.nextInt();
v[i] = scan.nextInt();
}
scan.close();
int dp[][] = new int[n+1][x+1];
dp[0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= x; j++) {
if(j >= v[i]){
dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-v[i]] + w[i]);
}else{
dp[i][j] = dp[i-1][j];
}
}
}
System.out.println(dp[n][x]);
}
剩余字符组成新的整数是最小的
小C平时最喜欢玩数字游戏,最近他碰到一道有趣的数字题,他和他的好朋友打赌,一定能在10分钟内解出这道题,
成功完成,小C就可以得到好朋友送他的Switch游戏机啦,你能帮助小C赢得奖品吗?
题目是这样的:给定一个非负的、字符串形式的整形数字,例如“12353789”,字符串的长度也就是整形数字的位数
不超过10000位,并且字符串不会以0开头,小C需要挑选出其中K个数字(K小于字符串的长度)并删掉他们,使得剩
余字符组成新的整数是最小的。
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String str = scan.nextLine();
int k = scan.nextInt();
scan.close();
Deque<Integer> stack = new LinkedList<>();
char[] chars = str.toCharArray();
for(char c : chars){
while(!stack.isEmpty() && stack.peekLast() > c - '0' && k > 0){
stack.removeLast();
k--;
}
stack.addLast(c - '0');
}
while(k > 0){
stack.removeLast();
k--;
}
StringBuilder sb = new StringBuilder();
boolean leadZero = true;
while(!stack.isEmpty()){
if(stack.peekFirst() == 0 && leadZero){
stack.removeFirst();
continue;
}
leadZero = false;
sb.append(stack.removeFirst());
}
if(sb.length() == 0){
System.out.println("0");
}else{
System.out.println(sb.toString());
}
}
喝咖啡调试bug
import java.util.Scanner;
public class dajiang1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int N = in.nextInt();
int A = in.nextInt();
int X = in.nextInt();
int total = 0;
int resultTime = 0;
for (int i = 0; i < N; i++) {
total += in.nextInt();
}
int temp = X;
for (int i = 0; i < X; i++) {
if(total - A*60 > 0){
total -= A*60;
resultTime += 60;
temp--;
}
}
if(temp > 0){
resultTime += Math.ceil((double)total/A);
System.out.println(resultTime);
}else{
if(total > 480 - X*60){
System.out.println(0);
return;
}else{
System.out.println(resultTime + total);
}
}
}
}
吃零食,动态规划,更新时判断零食还够不够
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
class food{
int price;
int satisfy;
int num;
public food(int price, int satisfy, int num) {
this.price = price;
this.satisfy = satisfy;
this.num = num;
}
}
class account {
int totalStatisfy;
int[] numbers;
public account(int totalStatisfy) {
this.totalStatisfy = totalStatisfy;
}
}
public class dajiang2 {
public static int N;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
N = in.nextInt();
int T = in.nextInt();
account[] moneyMax = new account[T+1];
food[] foods = new food[N];
int result = 0;
for (int i = 0; i < N; i++) {
foods[i] = new food(in.nextInt(), in.nextInt(), in.nextInt());
}
moneyMax[0] = new account(0);
moneyMax[0].numbers = new int[N];
for (int i = 0; i < N; i++) {
moneyMax[0].numbers[i] = foods[i].num;
}
for (int i = 1; i <= T; i++) {
findMax(moneyMax, i, foods);
if(moneyMax[i].totalStatisfy > result) result = moneyMax[i].totalStatisfy;
}
System.out.println(result);
}
public static void findMax(account[] moneyMax, int point, food[] foods){
int max = 0;
moneyMax[point] = new account(0);
moneyMax[point].numbers = new int[N];
for (int i = 0; i < N; i++) {
moneyMax[point].numbers[i] = foods[i].num;
}
for (int i = 0; i < foods.length; i++) {
boolean whetherBuy = false;
if(point - foods[i].price >= 0 && moneyMax[point - foods[i].price].numbers[i] > 0){
if(moneyMax[point - foods[i].price].totalStatisfy + foods[i].satisfy > max){
max = moneyMax[point - foods[i].price].totalStatisfy + foods[i].satisfy;
moneyMax[point].totalStatisfy = max;
for (int j = 0; j < N; j++) {
moneyMax[point].numbers[j] = moneyMax[point - foods[i].price].numbers[j];
}
moneyMax[point].numbers[i]--;
}
}
}
}
}