C++算法题

十进制转八进制

image-20240516115614109

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
using namespace std;
void eightSystem(int num) {
if (num < 8)
{
cout << num; //进制几次
return; //停止递归
}
eightSystem(num / 8); //整除再进入函数体
cout << num % 8; //输出余数
}
int main() {
int a;
cin >> a;
eightSystem(a);
return 0;
}

二的幂次方

image-20240516115637296

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<iostream>
using namespace std;
#include<math.h>

void two(int x) {
int i = 14;
while (i >= 0)
{
if (pow(2, i) <= x) //找到最接近目标值的2的次数
{
if (i == 1) cout << "2"; //剩下一个2
else if (i == 0) cout << "2(0)"; //剩下一个1
else {
cout << "2(";
two(i); //继续递归
cout << ")";
}
x -= pow(2, i);
if (x != 0) cout << "+";
}
i--;
}
}
int main() {
two(137);
return 0;
}

神牛果

image-20240602152924562

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
#include<algorithm>
using namespace std;
int a[10000] = {}; //存放牛的肚量
int main() {
int n; //牛的数量
cin >> n;
int b=0; //存放每组牛的数量
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
sort(a, a + n); //排序 1 2 5 8 1+8 2+5
//搭配 最大的和最小的搭配
for (int i = 0; i < n/2; i++)
{
if (b < a[i] + a[n - i - 1])
{
b = a[i] + a[n - i - 1];//存放和
}
}
cout << b;
return 0;
}

笨小孩

image-20240602152939275

image-20240602153006614

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
#include<algorithm>
using namespace std;
int a[10000];
int main() {
int n, x,time=0;
cin >> n >> x;
for (int i = 0; i < n; i++)
{
cin >> a[i]; // 存放每门课
}
sort(a, a + n);
for (int i = 0; i < n; i++)
{
time += x * a[i]; //每门课花费的时间
//学完一门课 花的时间变快
if (x != 1)
{
x--;
}
}
cout << time;
return 0;
}

美元汇率

image-20240602153038998

image-20240602153044148

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include<iostream>
using namespace std;
int main() {
int k=1;//当天是美元还是马克
int n; //天数
int a[101] = {}; //存放汇率
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> a[i]; // 存放每天的汇率
}
double x=100; //手里的钱
for (int i = 0; i < n; i++)
{
//如果手里是美元
if(k==1){
//第二天汇率小于第一天换成马克
if(a[i+1] < a[i]){
// 100 400 400=100*(400 / 100)
x = x * (a[i] / 100);
k=0; //变成马克
}
}
//如果手里是马克
if(k==0) {
if(a[i+1] > a[i]){
x = x /a[i] * 100;
k=1; //变成美元
}
}
}
//最后一天一定要是美元 最后一项
if(k==0) x = x /a[n-1] * 100;
printf("%.2lf\n",x);
return 0;
}

力扣算法刷题——备战蓝桥杯

1月9号之前的算法题

之前做了很多算法题,但是因为没有写笔记的原因,效果不太好,先把之前写的算法题的代码都放上来。以后写的算法题,要做好笔记。因为力扣做题都是给你一个函数的模版让你写题目,一般都是有返回值的,所以都可以放一个代码中去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
package December;

import javax.rmi.CORBA.Util;
import java.util.*;

class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
int[] arr = new int[]{1,2,3,4};
runningSum(arr);
canConstruct("aab","baa");
solution.minOperations("110");
System.out.println(solution.secondHighest("ck077"));
int[] arr1 = new int[]{-1,0,3,9,11,13,22,27,33,57,66,77};
// int[] arr = new int[]{-1,0,3,9,11,13,22,27,33,57,66,77};
int i = searchInsert(arr1, 1);
System.out.println(i);
int[] nums = new int[]{-2,1,-3,4,-1,2,1,-5,4};
solution.twoSum(nums,8);
solution.maxSubArray(nums);
solution.lengthOfLongestSubstring("pwwkep");
System.out.println("123456789".substring(2, 4));
String s1 = "ab",s2 = "eidboaoo";
solution.checkInclusion(s1, s2);
solution.mostCompetitive(new int[]{2,4,3,3,5,4,9,6},4);
}
// 力扣P1673贪心算法 自己半暴力做出来的 题解都用了数据栈 所以88个点只过了86个 后面学数据栈回头再来做一下
// public int[] mostCompetitive(int[] nums, int k) {
// int len = nums.length;
// int[] ints = new int[k];
// int min=0;
// int start = 0;
// for (int x = 0;x<k;x++){
// for (int n = start; n < len-k+x;n++){
// if (nums[min] > nums[n+1]){
// min = n+1;
// }
// }
// ints[x] = nums[min];
// start = min;
// min +=1 ;
// }
// return ints;
// }
//正确解
public int[] mostCompetitive(int[] nums, int k) {
ArrayList<Integer> stack = new ArrayList<Integer>();
int n = nums.length;
int last = n-k;
for (int i = 0; i < n; i ++) {
while (stack.size()>0 && last>0 && stack.get(stack.size()-1)>nums[i]) {
stack.remove(stack.size()-1);
last --;
}
stack.add(nums[i]);
}
int[] res = new int[k];
for(int i = 0; i < k; i++){
res[i] = stack.get(i);
}
return res;
}

//P567 字符串排序优解
public boolean checkInclusion(String s1, String s2) {
int n1=s1.length(),n2=s2.length();
if (n1>n2) return false;
int[] cnt = new int[26];
for(int x = 0;x<n1;x++){
cnt[s1.charAt(x) - 'a'] -= 1;
}
int left = 0;
for (int i = 0; i < n2; i++) {
int str = s2.charAt(i) - 'a';
cnt[str] += 1;
while (cnt[str] > 0){
cnt[s2.charAt(left) - 'a'] -= 1;
left++;
}
if (i-left+1 == n1){
return true;
}
}
return false;
}
//力扣P1480
public static int[] runningSum(int[] nums) {
for (int i = 1; i < nums.length; i++) {
nums[i] += nums[i-1];
}
return nums;
}

// public boolean checkInclusion(String s1, String s2) {
// int n = s1.length(), m = s2.length();
// if (n > m) {
// return false;
// }
// int[] cnt = new int[26];
// for (int i = 0; i < n; ++i) {
// --cnt[s1.charAt(i) - 'a'];
// }
// int left = 0;
// for (int right = 0; right < m; ++right) {
// int x = s2.charAt(right) - 'a';
// ++cnt[x];
// while (cnt[x] > 0) {
// --cnt[s2.charAt(left) - 'a'];
// ++left;
// }
// if (right - left + 1 == n) {
// return true;
// }
// }
// return false;
// }


//力扣P383
public static boolean canConstruct(String ransomNote, String magazine) {
if(ransomNote.length() > magazine.length()) {
return false;
}
int[] cnt = new int[26];
for(char c : magazine.toCharArray()) {
cnt[c - 'a'] ++;
}
for(char c : ransomNote.toCharArray()) {
cnt[c - 'a'] --;
if(cnt[c - 'a'] < 0) {
return false;
}
}
return true;
}
//力扣P412
public List<String> fizzBuzz(int n) {
ArrayList<String> arrayList = new ArrayList<>();
for (int i = 1; i <= n; i++) {
if (i % 3 == 0 && i % 5 == 0){
arrayList.add("FizzBuzz");
}else if (i % 3 ==0){
arrayList.add("Fizz");
}else if (i % 5 == 0){
arrayList.add("Buzz");
}else {
arrayList.add(String.valueOf(i));
}
}
return arrayList;
}
//P876 链表中间节点
public ListNode middleNode(ListNode head) {
ListNode slow = head;
ListNode fast = head;

while (fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;

}
return slow;
}
//P1769
public int[] minOperations(String boxes) {
String[] split = boxes.split("");
int[] ints = new int[split.length];
for (int i=0;i<split.length;i++){
int count = 0;
for (int x=0;x<split.length;x++){
if (split[x].equals("1")){
count += Math.abs(x-i);
}
}
ints[i] = count;
}
return ints;
}

//力扣P1796
public int secondHighest(String s) {
ArrayList<Integer> ay = new ArrayList<>();
for (char i : s.toCharArray()){
if (i > 47 && i < 58){
if (!ay.contains(i - 48)){
ay.add(i-48);
}
}
}
Collections.sort(ay);
if (ay.size()>1){
return ay.get(ay.size()-2);
}
return -1;
}
//P35优解 双指针
public static int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length -1;
while (left <= right){
int middle = left + (right - left) / 2;
if (nums[middle] > target){
right = middle -1;
}else if (nums[middle] < target){
left = middle + 1;
}else {
return middle;
}
}
return right+1;
}
//P704二分查找
public int search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = (right - left) / 2 + left;
int num = nums[mid];
if (num == target) {
return mid;
} else if (num > target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return -1;
}
//P977 输入一个升序的数组,然后返回一个数据各位置平方,也是升序
public int[] sortedSquares(int[] nums) {
//第一种 自己就是直接每位平方再重新排序 执行时间5ms
//for (int i = 0; i < nums.length; i++) {
// nums[i] = nums[i]*nums[i];
//}
//Arrays.parallelSort(nums);
//return nums;
//下面是双指针
//思路 因为是升序,所以数的平方的最大值一定是两边,把这个大的数 放新数组右边 然后两界限往内夹
int[] result = new int[nums.length];
int k = result.length-1; //给result倒着插入的下标
int right = result.length-1; //右界限
int left = 0; //左界限
while(left <= right){ //当左边等于右边 停止
if (nums[left]*nums[left] < nums[right]*nums[right]){ //两边判断大小 右边大
result[k--] = nums[right]*nums[right]; //大的插入最新数组右边 右边下标-1
right--; //右界限往内移1
}else{ //左边大
result[k--] = nums[left]*nums[left]; //大的插入最新数组右边 左边下标-1
left++; //左界限往内移1
}
}
return result;
}
//P189 轮转数组
public void rotate(int[] nums, int k) {
//int count = nums.length;
//int newNums[] = new int[count];
//for (int i = 0; i < count; i++) {
// newNums[(i+k) % count] = nums[i];
//}
//System.arraycopy(newNums, 0, nums, 0, count); //打印
reversal(nums,0,nums.length-1);
reversal(nums,0,k-1);
reversal(nums,k,nums.length-1);

}
//反转 下标为start 和 end 间的反转
public int[] reversal(int[] nums,int start,int end){
while (start<end){
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
return nums;
}
//P283移动〇
public void moveZeroes(int[] nums) {
int n = nums.length,left = 0,right = 0;
while (right < n) {
if(nums[right] != 0){
res(nums,left,right);
left++;
}
right++;
}
}
public void res(int[] nums,int x,int y){
int temp = nums[x];
nums[x] = nums[y];
nums[y] = temp;
}
//p344 反转字符串
public void reverseString(char[] s) {
int left = 0,right = s.length-1;
while(left <= right){
char temp = s[left];
s[left] = s[right];
s[right] = temp;
left++;
right--;
}
}
//力扣P1832 全字母句
public boolean checkIfPangram(String sentence) {
boolean[] booleans = new boolean[26];
for (int i = 0; i < sentence.length(); i++) {
char c = sentence.charAt(i);
booleans[c - 'a'] = true;
}
for (boolean x : booleans){
if (!x){
return false;
}
}
return true;
}
//力扣217
public boolean containsDuplicate(int[] nums) {
Set<Integer> set = new HashSet<Integer>();
for (int x : nums) {
if (!set.add(x)) {
return true;
}
}
return false;
}
//p1 两数之和优解
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; ++i) {
if (hashtable.containsKey(target - nums[i])) { //是否有该key
return new int[]{hashtable.get(target - nums[i]), i};
}
hashtable.put(nums[i], i);
}
return new int[0];
}
//P3 无重复字符的最长子串
public int lengthOfLongestSubstring(String s) {
HashMap<Character, Integer> map = new HashMap<>();
int max = 0, start = 0;
for (int end = 0; end < s.length(); end++) {
char ch = s.charAt(end);
if (map.containsKey(ch)){
start = Math.max(map.get(ch)+1,start);
}
max = Math.max(max,end - start + 1);
map.put(ch,end);
}
return max;
}

//p53最大数组
public int maxSubArray(int[] nums) {
int ans = nums[0], previous = nums[0];
for(int i :nums){
previous = Math.max(previous+i, i);
ans = Math.max(previous, ans);
}
return ans;
}
//p88
public void merge(int[] nums1, int m, int[] nums2, int n) {
int p1 = m -1,p2 = n -1,length = m + n -1,i;
while (p1>=0 || p2 >= 0){
if (p1 == -1){
i = nums2[p2--];
}else if(p2 == -1){
i = nums1[p1--];
}
else if (nums1[p1] < nums2[p2]){
i = nums2[p2--];
}else {
i = nums1[p1--];
}
nums1[length--] = i;
}
}
public String reverseWords(String x) {
String[] s = x.split(" ");
for (int i = 0; i < s.length; i++) {
StringBuffer stringBuffer = new StringBuffer(s[i]);
s[i] = stringBuffer.reverse().toString();
}
return String.join(" ",s);
}
//P19 删除链表倒数第N个结点
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
ListNode first = head;
ListNode second = dummy;
for (int i = 0; i < n; ++i) {
first = first.next;
}
while (first != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
return dummy.next;
}
//力扣P1672
public int maximumWealth(int[][] accounts) {
int max = 0;
for (int[] i: accounts){
int max1 =0;
for (int k : i){
max1 += k;
}
if (max1 > max){
max = max1;
}
}
return max;
}

}

还没怎么学习的链表题目中也有几道,后面学数据结构的时候再巩固一下 自定义链表代码如下

1
2
3
4
5
6
7
8
package December;
public class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

力扣题记

力扣P1673贪心算法

  • 自己半暴力做出来的 题解都用了数据栈 所以88个点只过了86个 后面学数据栈回头再来做一下

image-20230109223549100

  • 没过的原因自己也知道,因为自己空间复杂度是k*nums.length也就是所需要的数组长度和原数组的长度的循环次数 下面是自己的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public int[] mostCompetitive(int[] nums, int k) {
int len = nums.length;
int[] ints = new int[k];
int min=0;
int start = 0;
//思路:从倒数k之前先找最小值(防止k取不够) 然后从该索引再开始 取的位置可以往后移一格 以此类推

for (int x = 0;x<k;x++){
for (int n = start; n < len-k+x;n++){
if (nums[min] > nums[n+1]){
min = n+1;
}
}
ints[x] = nums[min];
start = min;
min +=1 ;
}
return ints;
}
  • 但是python中似乎比较简单,因为可以从尾部删除,我用java模仿的话,模仿出来需要新建一个arrayList
  • 题解原理:看了很久才明白题解代码的巧妙之处先把数组中值加一个到列表,然后如果该值不满足三个任何条件中一个(代码中有),就再往列表加入一个数组的值,再把新加入的值和后面的数组的值比,如果比后面的大就删除。如此一直,直到删除的数够了(比如数组长度是10,我需要数组长度为3的最具竞争力的,那我需要把原数组的值删除7次,只要3个值),需要的最具竞争力的数组也够了。

下面是python和java对该题使用单调栈的代码对比

1
2
3
4
5
6
7
8
9
10
11
class Solution(object):
def mostCompetitive(self, nums, k):
stack = []
n = len(nums)
last = n-k
for i in range(n):
while stack and last and stack[-1] > nums[i]:
stack.pop()
last -= 1
stack.append(nums[i])
return stack[:k]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public int[] mostCompetitive(int[] nums, int k) {
ArrayList<Integer> stack = new ArrayList<Integer>();
int n = nums.length;
int last = n-k;
//核心代码是下面的循环
for (int i = 0; i < n; i ++) {
while (stack.size()>0 && last>0 && stack.get(stack.size()-1)>nums[i]) {
stack.remove(stack.size()-1);
last --;
}
stack.add(nums[i]);
}
int[] res = new int[k];
for(int i = 0; i < k; i++){
res[i] = stack.get(i);
}
return res;
}
}

力扣P136 异或算法

题目不难 简单来说就是找出数组中只存在一个的数 其他的数字都是出现过两次 找只出现过一次的那个数 利用到了 异或中的交换律 数组中所有的数都异或 有两个的 都会变成0 最后只会剩下出现过一次的数

1
2
3
4
5
6
7
8
class Solution {
public int singleNumber(int[] nums) {
for(int i=1;i<nums.length;i++){
nums[0] ^= nums[i];
}
return nums[0];
}
}

力扣P15 双指针

题目为给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

难点在防止重复的地方 代码讲解点都在代码中了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums); //先排序
List<List<Integer>> res = new ArrayList<>(); //创建一个list里面好添加需要的数据
for (int x = 0; x < nums.length - 2; x++) { //循环直到倒数第三个
if (nums[x] > 0) break; //如果第一位大于0 总和就永远不会小于0
if (x > 0 && nums[x] == nums[x - 1]) continue; //如果该数和前一位相同 暂停本次循环 防止重复数据
int y = x + 1, z = nums.length - 1; //设置左和右指针
while (y < z) {
int sum = nums[x] + nums[y] + nums[z]; //相加的总和值
if (sum < 0) { //小于0 左指针 向右
y++;
} else if (sum > 0) { //大于0 右指针向左
z--;
} else {
res.add(new ArrayList<Integer>(Arrays.asList(nums[x], nums[y], nums[z])));
while (y < z && nums[y] == nums[++y]) ; //当条件满足时 为满足不重复的三元组 左右指针的值就不能跟原来一样了 加入while循环 直到指针区间的两边 跟满足条件的时候不同
while (y < z && nums[z] == nums[--z]) ;
}
}
}
return res;
}

蓝桥杯题库

编号2120

题目不难,找到规律就行了。

image-20230315093825402

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
String Ax = scan.nextLine();
int num = Integer.parseInt(Ax.substring(1));
int[] a = new int[6]; //A9超出 所以设置6个
int[] b = new int[5];
int aNumOne = 1189; //定义初始值
int bNumOne = 841;
for(int i = 0;i<6;i++){
a[i] = aNumOne;
aNumOne = aNumOne / 2; //取整添加
}
for(int j = 0;j<5;j++){
b[j] = bNumOne;
bNumOne = bNumOne / 2;
}
if(num%2==0){
System.out.println(a[num/2]);//偶数按索引取数组
System.out.println(b[num/2]);
}else{
System.out.println(b[(num-1)/2]);//奇数数前后取头
System.out.println(a[(num+1)/2]);
}
scan.close();
}

编号468

回文日期

题目很清晰明了,但是需要讨论的特殊条件比较多。就是日期规范性,每个月每个天数不一样,还有日期开头不为0,学份12月以内,不可为0,等等。在我最初的版本都是有一条一条if规范出来的。后来优化算法的时候,发现有些测试点,蓝桥杯是没有设置一些特殊检查点的所以像30天和28 29这种特殊月。所以后面闰月和2月都没用添加判断语句,但是也顺利通过了,耗时有点久。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import java.util.*;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
int N = scan.nextInt();
int i = N+1;
int res = 99999999;
while(i<=99999999){
String num = i+"";
int yearage = i/1000000;
int fanzhuanyearage = yearage/10+yearage%10*10;//反转day
int yearlaster = i%1000000/10000;
int fanzhuanyearlaster = yearlaster/10+yearlaster%10*10; //反转month
int month = i%10000/100;
int day = i%100;
int lastday = i%10; //最后一天不能为0 因为反转以后首不为0
if(month <= 12 && day <= 31 && lastday != 0 && fanzhuanyearage<=31 && fanzhuanyearlaster<=12 && fanzhuanyearlaster != 0){
if(huiwen(num)){
//设置回文 为第一个
if(res > Integer.parseInt(num)){
res = Integer.parseInt(num);
System.out.println(num);
}
//如果为AB回文直接停止
if(ABhuiwen(num)){
System.out.println(num);
break;
}
}
}
i++;
}
scan.close();
}
//判断闰年
public static boolean ruiyear(String num){
int year = Integer.parseInt(num);
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
//判断回文数
public static boolean huiwen(String num){
char[] c = num.toCharArray();
return c[0] == c[7] && c[1] == c[6] && c[2] == c[5] && c[3] == c[4];

}
//判断AB回文数
public static boolean ABhuiwen(String num){
char[] c = num.toCharArray();
return c[0] == c[2] && c[2] == c[5] && c[5] == c[7] && c[1] == c[3] && c[3] == c[4] && c[4] == c[6];
}
}

今日小爬虫

1月27号 抖音刷到一个Java爬虫的案例 自己试着更改敲了一遍

难点在两次连接 所要实现的代码功能为 利用java爬虫爬取该页面中,点击图片后跳转的链接中的高清背景图

image-20230127143522704

跳转后的页面 我拿赵怀真举例 检查中利用标签如何使用 已经写在图片中了

image-20230127144106376

使用IDEA 需要导入jsoup包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package htmlPhoto;

import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;



public class htmlPhoto {
public static void main(String[] args) throws IOException {
//Java爬虫
//1.建立连接
//网页链接 https://pvp.qq.com/web201605/herolist.shtml
Connection connection = Jsoup.connect("https://pvp.qq.com/web201605/herolist.shtml");
//通过链接获取 Document对象
Document document = connection.get();
//2.找到ul标签对象
//通过Document对象 找class为 herolist clearfix的ul
Element elementUl = document.selectFirst("[class=herolist clearfix]");
//找ul中的li
assert elementUl != null;
Elements elementLis = elementUl.select("li");

//3.for 循环读取li集合
int countHero = 0; //共计下载的图片数量
for (Element elementLi:elementLis){
//得到li中的a-href的路径
Element elementA = elementLi.selectFirst("a");
//a标签中间的名字
assert elementA != null;
String heroName = elementA.text();
//获取href的内容 然后拼接前面的链接
String hrefUrl = elementA.attr("href");
String path = "https://pvp.qq.com/web201605/" + hrefUrl;
//创建新的连接
Connection connect = Jsoup.connect(path);
//根据链接创建新的document对象
Document newDocument = connect.get();
Element elementDiv = newDocument.selectFirst("[class=zk-con1 zk-con]");
//获取element中的style属性
assert elementDiv != null;
String backgroundURL = elementDiv.attr("style");
//background:url('//game.gtimg.cn/images/yxzj/img201606/skin/hero-info/545/545-bigskin-1.jpg') center 0
//裁出需要的图片地址 两个单引号中间
int left = backgroundURL.indexOf("'");
int right = backgroundURL.lastIndexOf("'");
String photoURL = backgroundURL.substring(left + 1, right);
URL url = new URL("https:" + photoURL);
//已经获取到了图片的路径 url了 只需要通过IO流进行下载即可
System.out.println("下载" + heroName+"的高清1080P图片...");
//输入流 读取刚刚的图片
InputStream is = url.openStream();
//输出流 下载到本地
FileOutputStream fos = new FileOutputStream("E://IOTest/wzImg/" + heroName + ".jpg");
//下载图片
byte[] bytes = new byte[1024];
int count = is.read(bytes);
while (count!=-1){
fos.write(bytes,0,count);
fos.flush();
count = is.read(bytes);
}
is.close();
fos.close();
countHero+=1;
}
System.out.println("共计"+countHero+"位英雄图片全部下载完成");
}
}

利用该案例以及方法的使用,可以用java爬虫到很多不加密网站的图片或者视频链接 进行下载 如图已下载到该文件夹

image-20230127185113640

BUG点

网页的一个BUG,我看网页中113个英雄,下载只有93个。我自己的代码是没什么问题的,然后检查中也是113个标签,当我不知所措的时候,我点开了网页的源代码。发现其中是从云中君开始的,也就是源代码中只有93英雄,但是检查中的确英雄数量是齐全的,所以应该是他网页的一些问题,但为什么这样我也不清楚,检查和源代码不一样,页面显示的效果竟然和源代码不一样。但是问题不大,思路已经清楚了。

image-20230131191045116

image-20230131191214943