1.每日吐槽
。。。没什么可吐槽的,昨天的每日一题是困难类型的,直接copy了,自己现在还没有能力去解决困难难度的题目,所以也就没有记录下来了
2.leetcode每日一题
36.有效的数独
请你判断一个 9x9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 ‘.’ 表示。
public class Solution36 {
public boolean isValidSudoku(char[][] board) {
//直接上暴力
//先判断行是否符合
for(char []row : board){
boolean []isLive = new boolean[9];
for(char ch : row){
if(ch != '.'){
if(!isLive[ch - '1']){
isLive[ch - '1'] = true;
}else {
return false;
}
}
}
}
//判断列是否符合条件
for(int i = 0;i < 9;i++){
boolean []isLive = new boolean[9];
for(int j = 0;j < 9;j++){
if(board[j][i] != '.'){
if(!isLive[board[j][i] - '1']){
isLive[board[j][i] - '1'] = true;
}else {
return false;
}
}
}
}
//判断九宫格是否符合条件
for(int i = 0;i < 9;i++){
int x = (i) / 3 * 3;
int y = 6;
if((i + 1) % 3 == 1){
y = 0;
}
if((i + 1) % 3 == 2){
y = 3;
}
boolean []isLive = new boolean[9];
for(int r = x;r < x + 3;r++){
for(int c = y;c < y + 3;c++){
if (board[r][c] != '.') {
if(!isLive[board[r][c] - '1']){
isLive[board[r][c] - '1'] = true;
}else {
return false;
}
}
}
}
}
return true;
}
}
今天的每日一题挺简单的,简单易懂,但是leetcode的官方题解一次遍历算是惊讶到我了,很nice
3. 53 最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
class Solution {
public int maxSubArray(int[] nums) {
int ans = nums[0];
int sum = 0;
for(int num: nums) {
if(sum > 0) {
sum += num;
} else {
sum = num;
}
ans = Math.max(ans, sum);
}
return ans;
}
}
万恶的动态规划。。。。
这题还有个版本,就是需要标记到最大子序的开始和结束下标。
大致题意:
最大子段和问题。给定由n个整数组成的序列,求序列中子段的最大和,若所有整数均为负整数时定义最大子段和为0。
例如, 当(a1,a2,a3,a4 ,a5,a6) = (-2,11,-4,13,-5,-2)时,最大子段和为: a2+a3+a4=20
输入格式:
第一行输入整数个数n(1≤n≤10000),再依次输入n个整数。
输出格式:
输出第一行为最大子段和,第二行为子段第一个数和最后一个数在整个序列中的位序。
输入样例1:
6
-2 11 -4 13 -5 -2
输出样例1:
20
2 4
附上代码:
public class SubSum {
void maxSubSum(int n,int []nums){
int pre = 0;
int []ans = new int[3]; //分别存储最大值,最大值对应的第一个下标和第二个下标
ans[0] = nums[0];
int left = 0;
int right = 0;
for(int i = 0;i < n;i++){
if(pre > 0){
pre = pre + nums[i];
right = i;
}else if(pre <= 0){
pre = nums[i];
left = i;
}
if(ans[0] < pre){
ans[0] = pre;
ans[1] = left;
ans[2] = right;
}
}
if(ans[0] > 0){
System.out.println(ans[0]);
System.out.println((ans[1] + 1) + " " + (ans[2] + 1));
}else {
System.out.println(0);
System.out.println(0 + " " + 0);
}
}
}
4. 86 分隔链表
给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。
你应当 保留 两个分区中每个节点的初始相对位置。
不考虑在源链表上进行操作的话还算是简单吧。
先建立一个哑节点,然后依次遍历链表,大于x的放在哑节点后面,小于的放在哑节点前面,注意两种节点的插入方式就像,然后删除哑节点。当然除此之外还要有个头节点的标记,不然完成分隔链表后找不到头节点。
代码:
import LeetCode.ListNode;
public class Solution86 {
public ListNode partition(ListNode head, int x) {
ListNode dumb = new ListNode();
ListNode first = dumb;
ListNode end = new ListNode();
end.next = dumb;
ListNode root = end;
boolean isHead = false;
while (head != null){
if(head.val >= x){
first.next = new ListNode(head.val);
first = first.next;
}else {
ListNode store = new ListNode(head.val);
store.next = dumb;
end.next = store;
end = store;
if(!isHead){
root = end;
isHead = true;
}
}
head = head.next;
}
end.next = end.next.next;
return !isHead ? end.next : root;
}
}
//这里有个LeetCode.ListNode包是自己根据LeetCode的节点要求建立的
//package LeetCode;
//
//public class ListNode {
// public int val;
// public LeetCode.ListNode next;
// public ListNode() {}
// public ListNode(int val) { this.val = val; }
// public ListNode(int val, LeetCode.ListNode next) { //this.val = val; this.next = next; }
//}
还有个是在原链表上操作的,考虑没什么时间了,明天或者后天有空想到再写吧,难度应该也不是很大。
OVER
2021/09/17 23:33