Q同學's world

千里之行,始于足下


  • 关于

  • 分类

  • 首页

  • 标签

  • 归档

  • 站点地图

设计容器

发表于 2019-08-04 | 更新于 2025-12-06 | 分类于 算法

设计一个支持在平均 时间复杂度 O(1) 下,执行以下操作的数据结构。
insert(val):当元素 val 不存在时,向集合中插入该项。
remove(val):元素 val 存在时,从集合中移除该项。
getRandom:随机返回现有集合中的一项。每个元素应该有相同的概率被返回。

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
class RandomizedSet {
public:
vector<int> v;
map<int, int> m;
bool insert(int val) {
if (m.find(val) != m.end()) {
return false;
}
v.push_back(val);
m[val] = v.size() - 1;
return true;
}
bool remove(int val) {
if (m.find(val) == m.end()) {
return false;
} else {
int i = m[val]; //
int last = v[v.size()-1];
m.erase(val);
v[i] = last;
v.pop_back();
if (v.size() != i) //
m[last] = i;
}
return true;
}
int getRandom() {
int n = v.size();
return v[rand()%n];
}
};

二分查找第一个比K大的数

发表于 2019-08-04 | 更新于 2025-12-06 | 分类于 算法

1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int find(vector<int> a, int k) {
int l = 0, r = a.size();
int id;
while (l <= r) {

int mid = l + (r - l) / 2;
if (a[mid] > k) {
id = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
return id;
}

2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int binary(vector<int> v, int x) {
int i = 0, j = v.size() - 1;
while (i < j) {
int mid = i + (j - i) / 2;
if (v[mid] >= x) {
j = mid;
} else {
i = mid + 1;
}

}

return i;
}

虚拟内存

发表于 2019-07-28 | 更新于 2025-12-06 | 分类于 操作系统
功能:

一:进程内存管理
它有助于进程进行内存管理,主要体现在:
1.内存完整性:由于虚拟内存对进程的”欺骗”,每个进程都认为自己获取的内存是一块连续的地址。我们在编写应用程序时,就不用考虑大块地址的分配,总是认为系统有足够的大块内存即可。
2.安全:由于进程访问内存时,都要通过页表来寻址,操作系统在页表的各个项目上添加各种访问权限标识位,就可以实现内存的权限控制。
二:数据共享
通过虚拟内存更容易实现内存和数据的共享。
在进程加载系统库时,总是先分配一块内存,将磁盘中的库文件加载到这块内存中,在直接使用物理内存时,由于物理内存地址唯一,即使系统发现同一个库在系统内加载了两次,但每个进程指定的加载内存不一样,系统也无能为力。
而在使用虚拟内存时,系统只需要将进程的虚拟内存地址指向库文件所在的物理内存地址即可。如上文图中所示,进程 P1 和 P2 的 B 地址都指向了物理地址 C。
而通过使用虚拟内存使用共享内存也很简单,系统只需要将各个进程的虚拟内存地址指向系统分配的共享内存地址即可。
三:SWAP
虚拟内存可以让帮进程”扩充”内存。
我们前文提到了虚拟内存通过缺页中断为进程分配物理内存,内存总是有限的,如果所有的物理内存都被占用了怎么办呢?
Linux 提出 SWAP 的概念,Linux 中可以使用 SWAP 分区,在分配物理内存,但可用内存不足时,将暂时不用的内存数据先放到磁盘上,让有需要的进程先使用,等进程再需要使用这些数据时,再将这些数据加载到内存中,通过这种”交换”技术,Linux 可以让进程使用更多的内存。

二叉搜索树中序后继

发表于 2019-07-26 | 更新于 2025-12-06 | 分类于 算法

给定一个结点,找出这个结点的后继结点
中序遍历:左 中 右
情况分类:
一:结点的右子树不为空
返回右子树的最左结点
二:结点的右子树为空
1.如果这个结点是根结点,直接返回NULL
2.如果这个结点是父节点的左儿子,直接返回父亲结点
3.如果这个结点是父节点的右儿子,不断向上找第一个结点,这个结点是他父亲结点的左儿子

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
// Definition for a Node.
/*
class Node {
public:
int val;
Node* left;
Node* right;
Node* parent;
};
*/
class Solution {
public:
Node* inorderSuccessor(Node* node) {

if (node->right) {
Node* p = node->right;
while (p->left) {
p = p->left;
}
return p;
} else {
if (node->parent == NULL)
return NULL;
if (node->parent->left == node)
return node->parent;
else {
Node *p = node->parent;
while (p && p->right == node) {
node = p;
p = p->parent;
}
return p;
}
}
}
};

二叉树的最近公共祖先

发表于 2019-07-26 | 更新于 2025-12-06 | 分类于 算法
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
/**
* Definition for a binary tree node.
* struct c {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* result;
bool isInside(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == NULL) {
return 0;
}
bool left, right;
left = isInside(root->left, p, q);
right = isInside(root->right, p, q);
if ((right && left) || ((root == p || root == q) && (left || right))) {
result = root;
return 0;
}
if (left || right || root == p || root == q)
return 1;
return 0;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
isInside(root, p, q);
return result;
}
};

一个进栈的所有出栈序列

发表于 2019-07-26 | 更新于 2025-12-06 | 分类于 算法
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
//给出出栈顺序  求所有进栈的序列 || 给出入栈顺序 求出栈顺序 
void print(stack<int> v) {
while (v.size() != 0) {
cout<<v.top()<<" ";
v.pop();
}
cout<<endl;
}
//a存放入栈序列,b模拟入栈, c存放可能的出栈的序列
void dfs(stack<int> a, stack<int> b, stack<int> c) {

if (a.size() == 0 && b.size() == 0 ) {
print(c);
return;
}

if (a.size() != 0) { //入栈
int val = a.top();
b.push(val);
a.pop();
dfs(a, b, c);
b.pop();
a.push(val);
}
if (b.size() != 0) { //出栈
int val = b.top();
c.push(val);
b.pop();
dfs(a, b, c);
c.pop();
b.push(val);
}

return;
}

二叉树展开成链表

发表于 2019-07-26 | 更新于 2025-12-06 | 分类于 算法

给定一个二叉树,原地将它展开为链表。
例如,给定二叉树
1
/ \
2 5
/ \ \
3 4 6
展开为:
1-2-3-4-5-6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* last;
void flatten(TreeNode* root) {
if (root == NULL) return;
flatten(root->right);
flatten(root->left);
root->right = last;
root->left = NULL;
last = root;
}
};

链接:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list

环形链表

发表于 2019-07-26 | 更新于 2025-12-06 | 分类于 算法

一个含有循环链表的链表怎么求它开始循环的入口?
给出一个循环链表的例子:
1->2->3->4->5->3 最后5又指向了3,也就是说3->4->5->3形成了一个环
假设非环形的长度是x, 环形的长度是y, 链表总长度是n = x + y
思路:
两个指针, fast一次走两步, slow一次走一步, 总有一次他们会在环的某一个位置相遇。
于是可以列出关系表达式:
fast = 2slow (一个走一步,一个走两步,走了相同的时间)
fast = slow + ny (fast比slow多走了n圈的环)
2slow = slow + n
y -> slow = ny
得出了关键的表达式: slow = n
y, 假设一下slow处于环形起点的时候,n*y 圈之后还会回到起点。但是,slow是从链表的起点开始的,所以从入口要回退x步, 就是fast和slow相遇的点, 也就是说 非环形的链表长度x 等于 fast和slow最后相遇的节点到环形入口的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;

while (fast != NULL && fast->next != NULL) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) {
break;
}
}
if (fast == NULL || fast->next == NULL)
return NULL;
fast = head;

while(fast != slow) {
fast = fast->next;
slow = slow->next;
}
return fast;
}
};

删除链表重复元素

发表于 2019-07-26 | 更新于 2025-12-06 | 分类于 算法

输入: 1->2->3->3->4->4->5
输出: 1->2->5

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
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* h = NULL;
ListNode* pre = NULL;
ListNode* cur = head;
ListNode* r = NULL;
while (cur != NULL) {
if (juge(pre, cur) && juge(cur, cur->next)) {
if (h == NULL) {
h = new ListNode(cur->val);
r = h;
} else {
r->next = new ListNode(cur->val);
r = r->next;
}
}
pre = cur;
cur = cur->next;
}
return h;
}
bool juge(ListNode* node1, ListNode* node2) {
if (node1 == NULL || node2 == NULL || node1->val != node2->val) {
return true;
}
return false;
}
};

k个一组翻转链表

发表于 2019-07-26 | 更新于 2025-12-06 | 分类于 算法

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

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
class Solution {
public:
ListNode* reverse(ListNode* root) {
ListNode* pre = NULL;
ListNode* node = root;
ListNode* next;
while (node != NULL) {
next = node->next;
node->next = pre;
pre = node;
node = next;
}
return pre;
}

ListNode* reverseKGroup(ListNode* head, int k) {
if (head == NULL || head->next == NULL || k == 1) return head;
ListNode* result = new ListNode(-1);
ListNode* r = result;

while (head != NULL) {
int i;
ListNode* start = head;
ListNode* next;
for (i = 1; i < k && head != NULL; i++) head = head->next;
if (i <= k && head == NULL) {
r->next = start;
break;
} else {
next = head->next;
head->next = NULL;
r->next = reverse(start);
r = start;
head = next;
}
}
return result->next;
}
};

LRU

发表于 2019-07-25 | 更新于 2019-08-04
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
class LRUCache {
public:
list<int> link;
map<int, int> m;
int capacity;
LRUCache(int capacity) {
this->capacity = capacity;
}

int get(int key) {
if(m.find(key) == m.end()) {
return -1;
} else {
link.remove(key);
link.push_front(key);
}
return m[key];
}

void put(int key, int value) {
if (m.find(key) != m.end()) { //已存在
m[key] = value;
link.remove(key);
link.push_front(key);
} else { //不存在
if (m.size() >= capacity) {
int keyLast = link.back();
link.pop_back();
m.erase(keyLast);

link.push_front(key);
m[key] = value;
} else {
m[key] = value;
link.push_front(key);
}
}
}
};

快速排序三数取中

发表于 2019-07-25 | 更新于 2025-12-06 | 分类于 算法

给一个有序的数组,那代码的时间复杂度就是O(n^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
class Solution {
public:

int partition(vector<int>& nums, int left, int right) {

int mid = (left + right) / 2;
if (nums[left] > nums[right])
swap(nums[left], nums[right]);
if (nums[mid] > nums[right])
swap(nums[mid], nums[right]);
if (nums[mid] > nums[left])
swap(nums[mid], nums[left]); //把中值换到最左边

int val = nums[left];
int i = left, j = right; //填坑法
while (i < j) {
while (i < j && nums[j] >= val) j--;
nums[i] = nums[j];
while (i < j && nums[i] <= val) i++;
nums[j] = nums[i];
}
nums[i] = val;
return i;
}

void sort(vector<int>& nums, int left, int right) {
if (left >= right)
return;
int mid = partition(nums, left, right);
sort(nums, left, mid-1);
sort(nums, mid + 1, right);
}
vector<int> sortArray(vector<int>& nums) {

sort(nums, 0, nums.size()-1);
return nums;
}
};

没有优化的快排贴一下:
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
int pattern(int l,int r)
{
int i = l,j = r;
while(i<j)
{
while(i<j && a[i]<=a[j])
j--;
if(i<j)
swap(a[i],a[j]);
while(i<j && a[i]<=a[j])
i++;
if(i<j)
swap(a[i],a[j]);
}
return i;
}

void sort(int i,int j)
{
if(i<j)
{
int mid = pattern(i,j);
sort(i,mid-1);
sort(mid+1,j);
}
}

冒泡优化

发表于 2019-07-17 | 更新于 2025-12-06 | 分类于 算法

优化1 没有进行过交换结束
优化2 通过记录最后交换的位置,及终点的位置
优化3 波浪排序+优化1+优化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
#if 0
#include<bits/stdc++.h>
using namespace std;
int a[10000];
int n;
void sort(int a[], int n) {
bool flag = 0;
int k = n-1;
int last;
for (int i = 0; i < n-1; i++) {
flag = 0;
for (int j = 0; j < k; j++) {
sum++;
if (a[j] > a[j+1]) {
flag = 1;
last = j;
swap(a[j], a[j+1]);
}
}
if (flag == 0) {
break;
}
k = last;
}
}
int main()
{
while(1) {
sum = 0;
cin>>n;
for (int i = 0; i < n; i++) {
a[i] = rand() % n;
}
sort(a, n);
for(int i = 0; i < n; i++)
cout<<a[i]<<" ";

}
}

#endif

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
#if 0                      //波浪排序 就上两种优化
#include<bits/stdc++.h>
using namespace std;
int a[100000],n;
void sort(int a[], int n) {
int left = 0, right = n-1;
int flag = 0;
int last;
while (left < right) {
for (int i = left; i < right; i++) {
sum++;
if (a[i] > a[i+1]) {
swap(a[i], a[i+1]);
flag = 1;
last = i;
}
}
if (flag == 0) break;
right = last;
flag = 0;
for (int j = last; j > left; j--) {
sum++;
if (a[j] < a[j-1]) {
swap(a[j], a[j-1]);
flag = 1;
last = j;
}
}
if (flag == 0) break;
left = last;
}
}
int main()
{
while(1) {
cin>>n;
for (int i = 0; i < n; i++) {
a[i] = rand() % n;
}
sort(a, n);
for(int i = 0; i < n; i++)
cout<<a[i]<<" ";

}
}
#endif

链表|排序

发表于 2019-07-16 | 更新于 2025-12-06 | 分类于 算法

一:归并实现
1.递归写法
2.非递归写法,数组模拟递归(STL里源码思路)
二:插入实现

归并递归写法:

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
class Solution {
public:
ListNode* merge(ListNode* left, ListNode* right) {
ListNode* result = new ListNode(-1);
ListNode* r = result;
while (left != NULL && right != NULL) {
if (left->val <= right->val) {
r->next = left;
r = r->next;
left = left->next;
} else {
r->next = right;
r = r->next;
right = right->next;
}
}
if (left != NULL) r->next = left;
if (right != NULL) r->next = right;
return result->next;
}
ListNode* sortList(ListNode* head) {
if (head == NULL || head ->next == NULL) return head;
ListNode* pre = NULL;
ListNode* fast = head, *slow = head;
while (fast != NULL && fast->next != NULL) {
pre = slow;
fast = fast->next->next;
slow = slow->next;
}
pre->next = NULL;
ListNode* left = sortList(head);
ListNode* right = sortList(slow);
return merge(left, right);
}
};

归并非递归写法:
第二种着实很难理解,模拟了很久。敬畏敬畏。大道至简,就是这样哇。

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
class Solution {
public:
ListNode* merge(ListNode* l1, ListNode* l2) {
ListNode* result = new ListNode(-1);
ListNode* r = result;
while (l1 && l2) {
if (l1->val <= l2->val) {
r->next = l1;
r = r->next;
l1 = l1->next;
} else {
r->next = l2;
r = r->next;
l2 = l2->next;
}
}
if (l1) {
r->next = l1;
}
if (l2) {
r->next = l2;
}
return result->next;
}
ListNode* table[64] = {NULL};
int fill = 0;
int i = 0;
ListNode* carry;
ListNode* sortList(ListNode* head) {
if (head == NULL || head->next == NULL) return head;
while (head != NULL) {
ListNode* next = head->next;
head->next = carry;
carry = head;
i = 0;
while (i < fill && table[i]) {
table[i] = merge(carry, table[i]);
carry = NULL;
swap(carry, table[i++]);
}
swap(carry, table[i]);
if(i == fill) fill++;
head = next;
}
ListNode* result;
for (int i = 1; i < fill; i++) {
table[i] = merge(table[i], table[i-1]);
}
return table[fill-1];
}
};

插入排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
ListNode* result = new ListNode(INT_MIN);
ListNode* r = result;
ListNode* next;
while (head != NULL) {
next = head->next;
ListNode* r = result;
while (r != NULL && r->next != NULL && r->next->val < head->val) {
r = r->next;
}
head->next = r->next;
r->next = head;

head = next;
}
return result->next;
}
};

进程

发表于 2019-07-06 | 更新于 2025-12-06 | 分类于 操作系统

一:

线程和进程各自有什么区别和优劣呢?

  • 进程是资源分配的最小单位,线程是程序执行的最小单位。
  • 进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据的,使用相同的地 址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。
  • 线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。
  • 但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。

全排列

发表于 2019-06-25 | 更新于 2025-12-06 | 分类于 算法
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
//全排列 
#if 0
#include<bits/stdc++.h>
using namespace std;
void fun(int a[],int k,int m)
{
if(k == m)
{
for(int i=0; i<=m; i++)
cout<<a[i]<<" ";
cout<<endl;
}
for(int i=k; i<=m; i++)
{
swap(a[k],a[i]);
fun(a,k+1,m);
swap(a[k],a[i]);
}
}


int main()
{
int n;
int a[100];
cin>>n;
for(int i=0; i<n; i++)
{
cin>>a[i];
}
fun(a,0,n-1);

}
#endif

动态规划

发表于 2019-06-25 | 更新于 2025-12-06 | 分类于 算法
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
1.KMP
/*KMP算法
查询字符串a中 是否包含 字符串b
ababcabcacbab
abcac
*/

void getNext(string str) {
int k = 0;
for (int i = 1; i < str.size(); i++) {
while (k > 0 && str[i] != str[k])
k = next[k-1]; //精髓
if (str[i] == str[k]) k++;
next[i] = k;
}
}

int kmp(string s1, string s2) {
int i = 0, j = 0;
for (i = 0; i < s1.size() && j < s2.size(); i++) {
if (s1[i] == s2[j]) {
j++;
} else {
j = next[j-1]; //需要感受
}
}
if (j == s2.size()) return i - s2.size(); //返回第一次匹配的的下标
return -1;
}
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
2.背包问题  
// 01背包问题
// f[i][j]代表了 前i个物品的时候 容量为j的时候的最大的价值量,其中j必须是从v ...0的,因为每一个物品要选一次!!!

{

int m,n; //m:背包的容量 n:物品的个数
cin>>m>>n;
int w[n+10]; //每个物品的重量
int c[n+10]; //每个物品的价值
int f[m+10]; //f[k]代表 k个物品的时候,能装的最大的价值
memset(f,0,sizeof(f));
for(int i=0; i<n; i++)
{
cin>>w[i]>>c[i];
}
for(int i=0; i<n; i++)
{
for(int v = m; v>=w[i]; v--)
{
f[v] = max(f[v],f[v-w[i]] + c[i]);
}
}
cout<<f[m]<<endl;
}


//完全背包问题
{
int m,n; //m:背包的容量 n:物品的个数
cin>>m>>n;
int w[n+10]; //每个物品的重量
int c[n+10]; //每个物品的价值
int f[m+10]; //f[k]代表 k个物品的时候,能装的最大的价值
memset(f,0,sizeof(f));
for(int i=0; i<n; i++)
{
cin>>w[i]>>c[i];
}
for(int i=0; i<n; i++)
{
for(int v = w[i]; v<=m; v++)
{
f[v] = max(f[v],f[v-w[i]] + c[i]);
}
}
cout<<f[m]<<endl;
}
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
3.最大上升 子序列 
/*给出 [4,2,4,5,3,7],LIS 是 [2,4,5,7],返回 4
*/

int fun(int a[],int n)
{
int b[n]; //截至到i 最大的上升子序列 的个数
for(int i=0; i<n; i++)
b[i] = 1;
for(int i=1; i<n; i++)
{
int max = -1;
for(int j=0; j<i; j++) //找出前面比 此时的x 小的,并且 连续数最 大的 ~!!!
{
if(a[j] < a[i] && b[j] > max)
{
max = b[j];
}
}
if(max != -1)
b[i] = max +1;
}
int maxx = 0;
for(int i=0; i<n; i++)
maxx = max(b[i],maxx);
return maxx;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
最大子数组和
4.{
int a[] = {1, -2, 3, -4, 5, 6, -7};
int n = sizeof(a) / sizeof(int);
int max = INT_MIN;
int k = INT_MIN;
for (int i = 0; i < n; i++) {
if (k > 0) {
k += a[i];
} else {
k = a[i];
}
if (k > max) {
max = k;
}
}
}

排序算法

发表于 2019-06-25 | 更新于 2025-12-06 | 分类于 算法
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
//排序算法有 冒泡  / 快排/ 选择/堆排序/  归并 / 桶排序 /

//1.冒泡排序
#if 0
#include<bits/stdc++.h>
using namespace std;

void sort(int a[],int n)
{
for(int i=0; i<n-1; i++)
{
for(int j=0; j<n-i-1; j++) //
{
if(a[j] > a[j+1])
swap(a[j],a[j+1]);
}
}
}
int main()
{
int a[1000];
int n;
cin>>n;

for(int i=0; i<n; i++)
cin>>a[i];
sort(a,n);

for(int i=0; i<n; i++)
cout<<a[i]<<" ";

}
#endif


//1.1 快速排序
#if 0
#include<bits/stdc++.h>
using namespace std;
int a[1000];
int pattern(int l,int r)
{
int i = l,j = r;
while(i<j)
{
while(i<j && a[i]<=a[j])
j--;
if(i<j)
swap(a[i],a[j]);
while(i<j && a[i]<=a[j])
i++;
if(i<j)
swap(a[i],a[j]);
}
return i;
}

void sort(int i,int j)
{
if(i<j)
{
int mid = pattern(i,j);
sort(i,mid-1);
sort(mid+1,j);
}
}

int main()
{

int n;
cin>>n;

for(int i=0; i<n; i++)
cin>>a[i];
sort(0,n-1);

for(int i=0; i<n; i++)
cout<<a[i]<<" ";

}
#endif
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
//2.选择排序

#if 0
#include<bits/stdc++.h>
using namespace std;

void sort(int a[],int n)
{
int num;
for(int i=0; i<n-1; i++)
{
num = i;
for(int j=i+1; j<n; j++)
{
if(a[j] > a[num])
num = j;
}
if(num != i)
swap(a[num],a[i]);
}
}
int main()
{
int a[1000];
int n;
cin>>n;

for(int i=0; i<n; i++)
cin>>a[i];
sort(a,n);

for(int i=0; i<n; i++)
cout<<a[i]<<" ";

}
#endif
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
//3. 归并排序
#if 0
#include<bits/stdc++.h>
using namespace std;
int r[1000],r1[1000];
void merge(int s,int m,int t)
{
int i=s,j=m+1,k=s;

while(i<=m && j<=t)
{
if(r[i]<=r[j])
r1[k++] = r[i++];
else
r1[k++] = r[j++];
}


while(i<=m)
r1[k++] = r[i++];
while(j<=t)
r1[k++] = r[j++];

for(int z=s; z<=t; z++)
r[z] = r1[z];


}
void sort(int s,int t)
{

if(s>=t)
return;

int m = (s+t)/2;
sort(s,m);
sort(m+1,t);
merge(s,m,t);
}

int main()
{

int n;
cin>>n;
for(int i=0; i<n; i++)
{
cin>>r[i];
}
sort(0,n-1);

for(int i=0; i<n; i++)
cout<<r1[i]<<" ";

}
#endif
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
//4.堆排序

#if 0
#include<bits/stdc++.h>
using namespace std;
int a[100000];
int n;

void sift(int s,int t)
{
int i=s,j=2*s;
while(j<=t)
{

if(a[j+1] > a[j] && j<t)
j++;
if(a[i] > a[j])
break;
else
{
swap(a[i],a[j]);
i = j;
j = 2*i;
}

}

}

void sort(int n)
{
for(int i=n/2; i>=1; i--)
{
sift(i,n);
}

for(int i=1; i<n; i++)
{
swap(a[1],a[n-i+1]);
sift(1,n-i);

}
}


int main()
{

cin>>n;
for(int i=1; i<=n; i++)
{
a[i] = n-i;
}
sort(n);

for(int i=1; i<=n; i++)
cout<<a[i]<<" ";

}
#endif
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
//基数排序

#if 0
#include<bits/stdc++.h>
using namespace std;
int head;
struct Node
{
int key;
int next;
};
struct QueueNode
{
int front,rear;
};

void distribute(Node r[],int n,QueueNode q[],int m)
{
int i = 0; //默认为0 最后的next为 -1
while(1)
{
int key = r[i].key;
if(q[key].front==-1)
{
q[key].front = i;
}
else
{
r[q[key].rear].next = i;
}
q[key].rear = i;
i = r[i].next;


if(i == -1)
break;
}

}

void collection(Node r[],int n,QueueNode q[],int m)
{
int k = 0;
while(q[k].front==-1)
k++;
int first = q[k].front;
int last = q[k].rear;
head = first;

while(k<m)
{
k++;
if(q[k].front!=-1)
{
r[last].next = q[k].front;
last = q[k].rear;
}
}
r[last].next = -1;
}

void bucketSort(Node r[],int n,QueueNode q[],int m)
{
for(int i=0; i<n; i++)
r[i].next = i+1;
r[n-1].next = -1;

for(int i=0; i<m; i++)
{
q[i].front = q[i].rear = -1;
}


distribute(r,n,q,m);
collection(r,n,q,m);


}

int main()
{
Node r[1000];
QueueNode q[1000];

int n;
cin>>n;

for(int i=0; i<n; i++)
r[i].key = n-i;

bucketSort(r,n,q,100);


while(head!=-1)
{
cout<<r[head].key<<" ";
head = r[head].next;
}

}
#endif
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
//插入排序
#if 0
#include<bits/stdc++.h>
using namespace std;

void sort(int a[],int n)
{
for(int i=2; i<=n; i++)
{
a[0] = a[i];
int j;
for(j=i-1; a[j] > a[0]; j--)
{
a[j+1] = a[j];
}
a[j+1] = a[0];
}
}


int main()
{
int a[100];
int n;
cin>>n;
for(int i=1; i<=n; i++)
cin>>a[i];
sort(a,n);

for(int i=1; i<=n; i++)
cout<<a[i]<<" ";

}
#endif
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

//希尔排序
#if 0
#include<bits/stdc++.h>
using namespace std;

void sort(int a[],int n)
{
for(int d=n/2; d>=1; d/=2)
{
for(int i=d+1; i<=n; i++)
{
a[0] = a[i];
int j;
for(j=i-d; j>0&&a[0]<a[j]; j-=d)
{
a[j+d] = a[j];
}
a[j+d] = a[0];
}
}
}

int main()
{
int a[100];
int n;
cin>>n;
for(int i=1; i<=n; i++)
cin>>a[i];
sort(a,n);

for(int i=1; i<=n; i++)
cout<<a[i]<<" ";
}
#endif

golang版本如下:

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
func sortArray(nums []int) []int {
// quickSort(nums, 0, len(nums)-1)
// mergeDfsSort(nums, 0, len(nums)-1)
choiceSort(nums)
return nums
}


// 选择排序
func choiceSort(nums []int) {
n := len(nums)
for i := 1; i < n; i++ {
insertVal := nums[i]
j := i-1
for j >= 0 && nums[j] > insertVal {
nums[j+1] = nums[j]
j--
}

nums[j+1] = insertVal
}
}



// 归并排序
func mergeDfsSort(nums []int, left, right int) {
if left >= right {
return
}

mid := left + (right-left) / 2
mergeDfsSort(nums, left, mid)
mergeDfsSort(nums, mid+1, right)

mergeOnce(nums, left, mid, mid+1, right)
}

func mergeOnce(nums []int, aLeft, aRight, bLeft, bRight int) {
numsTemp := make([]int, 0, bRight-aLeft+1)

i, j := aLeft, bLeft
for i <= aRight && j <= bRight {
if nums[i] <= nums[j] {
numsTemp = append(numsTemp, nums[i])
i++
} else {
numsTemp = append(numsTemp, nums[j])
j++
}
}

for i <= aRight {
numsTemp = append(numsTemp, nums[i])
i++
}
for j <= bRight {
numsTemp = append(numsTemp, nums[j])
j++
}

copy(nums[aLeft:bRight+1], numsTemp)
}


// 快速排序
// 优化: https://chat.deepseek.com/share/ae3mlc7vdq4z6sm4iz
// 优化可以使用随机基准,避免数组本身是有序的情况下 复杂度上升到O(n2)
func quickSort(nums []int, left, right int) {
if left >= right {
return
}

mid := quickSortPartitionV1(nums, left, right)
quickSort(nums, left, mid-1)
quickSort(nums, mid+1, right)
}

func quickSortPartition(nums []int, left, right int) int {
i, j := left, right

for i < j {
for i < j && nums[i] <= nums[j] {
j--
}
if i < j {
nums[i], nums[j] = nums[j], nums[i]
}

for i < j && nums[i] <= nums[j] {
i++
}
if i < j {
nums[i], nums[j] = nums[j], nums[i]
}
}

return i
}

// 优化之后的版本
func quickSortPartitionV1(nums []int, left, right int) int {
randomIndex := left + rand.Intn(right-left+1)
nums[left], nums[randomIndex] = nums[randomIndex], nums[left]

i, j := left, right

for i < j {
for i < j && nums[i] <= nums[j] {
j--
}
if i < j {
nums[i], nums[j] = nums[j], nums[i]
}

for i < j && nums[i] <= nums[j] {
i++
}
if i < j {
nums[i], nums[j] = nums[j], nums[i]
}
}

return i
}

Http

发表于 2019-06-24 | 更新于 2025-12-06 | 分类于 计算机网络

—————->网站:
Http学习
请求头|响应头

1.信息代码:1xx,
2.成功代码:2xx,
3.重定向:3xx,
4.客户端错误:4xx,
5.服务器错误:5xx

=============================================================================

HTTP: Status 1xx (临时响应)
表示临时响应并需要请求者继续执行操作的状态代码。
详细代码及说明:

HTTP: Status 100 (继续)
->请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。
HTTP: Status 101 (切换协议)
->请求者已要求服务器切换协议,服务器已确认并准备切换。


HTTP Status 2xx (成功)
表示成功处理了请求的状态代码;
详细代码及说明:

HTTP Status 200 (成功)
-> 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。
HTTP Status 201 (已创建)
-> 请求成功并且服务器创建了新的资源。
HTTP Status 202 (已接受)
-> 服务器已接受请求,但尚未处理。
HTTP Status 203 (非授权信息)
-> 服务器已成功处理了请求,但返回的信息可能来自另一来源。
HTTP Status 204 (无内容)
-> 服务器成功处理了请求,但没有返回任何内容。
HTTP Status 205 (重置内容)
-> 服务器成功处理了请求,但没有返回任何内容。
HTTP Status 206 (部分内容)
-> 服务器成功处理了部分 GET 请求。


HTTP Status 3xx (重定向)
常见的代码

300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。


HTTP Status 4xx (请求错误)
->这些状态代码表示请求可能出错,妨碍了服务器的处理。

详细代码说明:
HTTP Status 400 (错误请求)
->服务器不理解请求的语法。
HTTP Status 401 (未授权)
->请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
HTTP Status 403 (禁止)
-> 服务器拒绝请求。
HTTP Status 404 (未找到)
->服务器找不到请求的网页。
HTTP Status 405 (方法禁用)
->禁用请求中指定的方法。
HTTP Status 406 (不接受)
->无法使用请求的内容特性响应请求的网页。
HTTP Status 407 (需要代理授权)
->此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
HTTP Status 408 (请求超时)
->服务器等候请求时发生超时。
HTTP Status 409 (冲突)
->服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。
HTTP Status 410 (已删除)
-> 如果请求的资源已永久删除,服务器就会返回此响应。
HTTP Status 411 (需要有效长度)
->服务器不接受不含有效内容长度标头字段的请求。
HTTP Status 412 (未满足前提条件)
->服务器未满足请求者在请求中设置的其中一个前提条件。
HTTP Status 413 (请求实体过大)
->服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
HTTP Status 414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。
HTTP Status 415 (不支持的媒体类型)
->请求的格式不受请求页面的支持。
HTTP Status 416 (请求范围不符合要求)
->如果页面无法提供请求的范围,则服务器会返回此状态代码。
HTTP Status 417 (未满足期望值)
->服务器未满足”期望”请求标头字段的要求。


HTTP Status 5xx (服务器错误)
->这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。
代码详细及说明:
HTTP Status 500 (服务器内部错误)
->服务器遇到错误,无法完成请求。
HTTP Status 501 (尚未实施)
->服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
HTTP Status 502 (错误网关)
->服务器作为网关或代理,从上游服务器收到无效响应。
HTTP Status 503 (服务不可用)
-> 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
HTTP Status 504 (网关超时)
->服务器作为网关或代理,但是没有及时从上游服务器收到请求。
HTTP Status 505 (HTTP 版本不受支持)
-> 服务器不支持请求中所用的 HTTP 协议版本。

网络端口号

发表于 2019-06-24 | 更新于 2025-12-06 | 分类于 计算机网络

21/tcp FTP 文件传输协议
22/tcp SSH 安全登录、文件传送(SCP)和端口重定向
23/tcp Telnet 不安全的文本传送
25/tcp SMTP Simple Mail Transfer Protocol (E-mail)
69/udp TFTP Trivial File Transfer Protocol
79/tcp finger Finger
80/tcp HTTP 超文本传送协议 (WWW)
88/tcp Kerberos Authenticating agent
110/tcp POP3 Post Office Protocol (E-mail)
113/tcp ident old identification server system
119/tcp NNTP used for usenet newsgroups
220/tcp IMAP3
443/tcp HTTPS used for securely transferring web pages
端口:0
服务:Reserved
说明:通常用于分析操作系统。这一方法能够工作是因为在一些系统中“0”是无效端口,当你试图使用通常的闭合端口连接它时将产生不同的结果。一种典型的扫描,使用IP地址为0.0.0.0,设置ACK位并在以太网层广播。

端口:1
服务:tcpmux
说明:这显示有人在寻找SGI Irix机器。Irix是实现tcpmux的主要提供者,默认情况下tcpmux在这种系统中被打开。Irix机器在发布是含有几个默认的无密码的帐户,如:IP、GUEST UUCP、NUUCP、DEMOS 、TUTOR、DIAG、OUTOFBOX等。许多管理员在安装后忘记删除这些帐户。因此HACKER在INTERNET上搜索tcpmux并利用这些帐户。

端口:7
服务:Echo
说明:能看到许多人搜索Fraggle放大器时,发送到X.X.X.0和X.X.X.255的信息。

端口:19
服务:Character Generator
说明:这是一种仅仅发送字符的服务。UDP版本将会在收到UDP包后回应含有垃圾字符的包。TCP连接时会发送含有垃圾字符的数据流直到连接关闭。HACKER利用IP欺骗可以发动DoS攻击。伪造两个chargen服务器之间的UDP包。同样Fraggle DoS攻击向目标地址的这个端口广播一个带有伪造受害者IP的数据包,受害者为了回应这些数据而过载。

端口:21
服务:FTP
说明:FTP服务器所开放的端口,用于上传、下载。最常见的攻击者用于寻找打开anonymous的FTP服务器的方法。这些服务器带有可读写的目录。木马Doly Trojan、Fore、Invisible FTP、WebEx、WinCrash和Blade Runner所开放的端口。

端口:22
服务:Ssh
说明:PcAnywhere建立的TCP和这一端口的连接可能是为了寻找ssh。这一服务有许多弱点,如果配置成特定的模式,许多使用RSAREF库的版本就会有不少的漏洞存在。

端口:23
服务:Telnet
说明:远程登录,入侵者在搜索远程登录UNIX的服务。大多数情况下扫描这一端口是为了找到机器运行的操作系统。还有使用其他技术,入侵者也会找到密码。木马Tiny Telnet Server就开放这个端口。

端口:25
服务:SMTP
说明:SMTP服务器所开放的端口,用于发送邮件。入侵者寻找SMTP服务器是为了传递他们的SPAM。入侵者的帐户被关闭,他们需要连接到高带宽的E-MAIL服务器上,将简单的信息传递到不同的地址。木马Antigen、Email Password Sender、Haebu Coceda、Shtrilitz Stealth、WinPC、WinSpy都开放这个端口。

端口:31
服务:MSG Authentication
说明:木马Master Paradise、Hackers Paradise开放此端口。

端口:42
服务:WINS Replication
说明:WINS复制

端口:53
服务:Domain Name Server(DNS)
说明:DNS服务器所开放的端口,入侵者可能是试图进行区域传递(TCP),欺骗DNS(UDP)或隐藏其他的通信。因此防火墙常常过滤或记录此端口。
端口:67
服务:Bootstrap Protocol Server
说明:通过DSL和Cable modem的防火墙常会看见大量发送到广播地址255.255.255.255的数据。这些机器在向DHCP服务器请求一个地址。HACKER常进入它们,分配一个地址把自己作为局部路由器而发起大量中间人(man-in-middle)攻击。客户端向68端口广播请求配置,服务器向67端口广播回应请求。这种回应使用广播是因为客户端还不知道可以发送的IP地址。

端口:69
服务:Trival File Transfer
说明:许多服务器与bootp一起提供这项服务,便于从系统下载启动代码。但是它们常常由于错误配置而使入侵者能从系统中窃取任何 文件。它们也可用于系统写入文件。

端口:79
服务:Finger Server
说明:入侵者用于获得用户信息,查询操作系统,探测已知的缓冲区溢出错误,回应从自己机器到其他机器Finger扫描。

端口:80
服务:HTTP
说明:用于网页浏览。木马Executor开放此端口。

端口:99
服务:gram Relay
说明:后门程序ncx99开放此端口。

端口:102
服务:Message transfer agent(MTA)-X.400 over TCP/IP
说明:消息传输代理。

端口:109
服务:Post Office Protocol -Version3
说明:POP3服务器开放此端口,用于接收邮件,客户端访问服务器端的邮件服务。POP3服务有许多公认的弱点。关于用户名和密码交 换缓冲区溢出的弱点至少有20个,这意味着入侵者可以在真正登陆前进入系统。成功登陆后还有其他缓冲区溢出错误。

端口:110
服务:SUN公司的RPC服务所有端口
说明:常见RPC服务有rpc.mountd、NFS、rpc.statd、rpc.csmd、rpc.ttybd、amd等

端口:113
服务:Authentication Service
说明:这是一个许多计算机上运行的协议,用于鉴别TCP连接的用户。使用标准的这种服务可以获得许多计算机的信息。但是它可作为许多服务的记录器,尤其是FTP、POP、IMAP、SMTP和IRC等服务。通常如果有许多客户通过防火墙访问这些服务,将会看到许多这个端口的连接请求。记住,如果阻断这个端口客户端会感觉到在防火墙另一边与E-MAIL服务器的缓慢连接。许多防火墙支持TCP连接的阻断过程中发回RST。这将会停止缓慢的连接。
端口:119
服务:Network News Transfer Protocol
说明:NEWS新闻组传输协议,承载USENET通信。这个端口的连接通常是人们在寻找USENET服务器。多数ISP限制,只有他们的客户才能访问他们的新闻组服务器。打开新闻组服务器将允许发/读任何人的帖子,访问被限制的新闻组服务器,匿名发帖或发送SPAM。

端口:135
服务:Location Service
说明:Microsoft在这个端口运行DCE RPC end-point mapper为它的DCOM服务。这与UNIX 111端口的功能很相似。使用DCOM和RPC的服务利用计算机上的end-point mapper注册它们的位置。远端客户连接到计算机时,它们查找end-point mapper找到服务的位置。HACKER扫描计算机的这个端口是为了找到这个计算机上运行Exchange Server吗?什么版本?还有些DOS攻击直接针对这个端口。

端口:137、138、139
服务:NETBIOS Name Service
说明:其中137、138是UDP端口,当通过网上邻居传输文件时用这个端口。而139端口:通过这个端口进入的连接试图获得NetBIOS/SMB服务。这个协议被用于windows文件和打印机共享和SAMBA。还有WINS Regisrtation也用它。

端口:143
服务:Interim Mail Access Protocol v2
说明:和POP3的安全问题一样,许多IMAP服务器存在有缓冲区溢出漏洞。记住:一种LINUX蠕虫(admv0rm)会通过这个端口繁殖,因此许多这个端口的扫描来自不知情的已经被感染的用户。当REDHAT在他们的LINUX发布版本中默认允许IMAP后,这些漏洞变的很流行。这一端口还被用于IMAP2,但并不流行。

端口:161
服务:SNMP
说明:SNMP允许远程管理设备。所有配置和运行信息的储存在数据库中,通过SNMP可获得这些信息。许多管理员的错误配置将被暴露在Internet。Cackers将试图使用默认的密码public、private访问系统。他们可能会试验所有可能的组合。SNMP包可能会被错误的指向用户的网络。

端口:177
服务:X Display Manager Control Protocol
说明:许多入侵者通过它访问X-windows操作台,它同时需要打开6000端口。

端口:389
服务:LDAP、ILS
说明:轻型目录访问协议和NetMeeting Internet Locator Server共用这一端口。

端口:443
服务:Https
说明:网页浏览端口,能提供加密和通过安全端口传输的另一种HTTP。

端口:456
服务:[NULL]
说明:木马HACKERS PARADISE开放此端口。

端口:513
服务:Login,remote login
说明:是从使用cable modem或DSL登陆到子网中的UNIX计算机发出的广播。这些人为入侵者进入他们的系统提供了信息。

端口:544
服务:[NULL]
说明:kerberos kshell

端口:548
服务:Macintosh,File Services(AFP/IP)
说明:Macintosh,文件服务。

端口:553
服务:CORBA IIOP (UDP)
说明:使用cable modem、DSL或VLAN将会看到这个端口的广播。CORBA是一种面向对象的RPC系统。入侵者可以利用这些信息进入系统。

端口:555
服务:DSF
说明:木马PhAse1.0、Stealth Spy、IniKiller开放此端口。
端口:568
服务:Membership DPA
说明:成员资格 DPA。

端口:569
服务:Membership MSN
说明:成员资格 MSN。

端口:635
服务:mountd
说明:Linux的mountd Bug。这是扫描的一个流行BUG。大多数对这个端口的扫描是基于UDP的,但是基于TCP的mountd有所增加(mountd同时运行于两个端口)。记住mountd可运行于任何端口(到底是哪个端口,需要在端口111做portmap查询),只是Linux默认端口是635,就像NFS通常运行于2049端口。

端口:636
服务:LDAP
说明:SSL(Secure Sockets layer)

端口:666
服务:Doom Id Software
说明:木马Attack FTP、Satanz Backdoor开放此端口

端口:993
服务:IMAP
说明:SSL(Secure Sockets layer)

端口:1001、1011
服务:[NULL]
说明:木马Silencer、WebEx开放1001端口。木马Doly Trojan开放1011端口。

端口:1024
服务:Reserved
说明:它是动态端口的开始,许多程序并不在乎用哪个端口连接网络,它们请求系统为它们分配下一个闲置端口。基于这一点分配从端口1024开始。这就是说第一个向系统发出请求的会分配到1024端口。你可以重启机器,打开Telnet,再打开一个窗口运行natstat -a 将会看到Telnet被分配1024端口。还有SQL session也用此端口和5000端口。

端口:1025、1033
服务:1025:network blackjack 1033:[NULL]
说明:木马netspy开放这2个端口。

端口:1080
服务:SOCKS
说明:这一协议以通道方式穿过防火墙,允许防火墙后面的人通过一个IP地址访问INTERNET。理论上它应该只允许内部的通信向外到达INTERNET。但是由于错误的配置,它会允许位于防火墙外部的攻击穿过防火墙。WinGate常会发生这种错误,在加入IRC聊天室时常会看到这种情况。

端口:1170
服务:[NULL]
说明:木马Streaming Audio Trojan、Psyber Stream Server、Voice开放此端口。

端口:1234、1243、6711、6776
服务:[NULL]
说明:木马SubSeven2.0、Ultors Trojan开放1234、6776端口。木马SubSeven1.0/1.9开放1243、6711、6776端口。

端口:1245
服务:[NULL]
说明:木马Vodoo开放此端口。

端口:1433
服务:SQL
说明:Microsoft的SQL服务开放的端口。

端口:1492
服务:stone-design-1
说明:木马FTP99CMP开放此端口。

端口:1500
服务:RPC client fixed port session queries
说明:RPC客户固定端口会话查询

端口:1503
服务:NetMeeting T.120
说明:NetMeeting T.120

端口:1524
服务:ingress
说明:许多攻击脚本将安装一个后门SHELL于这个端口,尤其是针对SUN系统中Sendmail和RPC服务漏洞的脚本。如果刚安装了防火墙就看到在这个端口上的连接企图,很可能是上述原因。可以试试Telnet到用户的计算机上的这个端口,看看它是否会给你一个SHELL。连接到600/pcserver也存在这个问题。

端口:1600
服务:issd
说明:木马Shivka-Burka开放此端口。

端口:1720
服务:NetMeeting
说明:NetMeeting H.233 call Setup。

端口:1731
服务:NetMeeting Audio Call Control
说明:NetMeeting音频调用控制。

端口:1807
服务:[NULL]
说明:木马SpySender开放此端口。

端口:1981
服务:[NULL]
说明:木马ShockRave开放此端口。

端口:1999
服务:cisco identification port
说明:木马BackDoor开放此端口。

端口:2000
服务:[NULL]
说明:木马GirlFriend 1.3、Millenium 1.0开放此端口。

端口:2001
服务:[NULL]
说明:木马Millenium 1.0、Trojan Cow开放此端口。

端口:2023
服务:xinuexpansion 4
说明:木马Pass Ripper开放此端口。

端口:2049
服务:NFS
说明:NFS程序常运行于这个端口。通常需要访问Portmapper查询这个服务运行于哪个端口。

端口:2115
服务:[NULL]
说明:木马Bugs开放此端口。

端口:2140、3150
服务:[NULL]
说明:木马Deep Throat 1.0/3.0开放此端口。

端口:2500
服务:RPC client using a fixed port session replication
说明:应用固定端口会话复制的RPC客户

123

Q-同學

Make a diffence

44 日志
7 分类
7 标签
RSS
GitHub
📚 文章目录
操作系统 (2)
• 虚拟内存
• 进程
工具 (8)
• HHKB
• linux基本命令整理
• mac chrome快捷键
• Git+Iterm
• vscode
• next主题
• hexo和Markdown的小用法
• 博客搭建教程
算法 (23)
• 字符串的排列
• 最长回文字串
• 实现trie
• 双指针例题1
• 最长上升子序列
• 最大 BST 子树
• 无重复字符的最长子串
• 递增顺序查找树
• 设计容器
• 二分查找第一个比K大的数
• 二叉搜索树中序后继
• 二叉树的最近公共祖先
• 一个进栈的所有出栈序列
• 二叉树展开成链表
• 环形链表
• 删除链表重复元素
• k个一组翻转链表
• 快速排序三数取中
• 冒泡优化
• 链表|排序
• 全排列
• 动态规划
• 排序算法
计算机网络 (2)
• Http
• 网络端口号
随想 (1)
• 天津之行
读书笔记 (7)
• 围城&英伟达
• 1984
• 动物庄园
• 美国商业大亨传奇
• 你当像鸟飞往你的山
• 霍乱时期的爱情
• 相约星期二
博客 (3)
• next主题
• hexo和Markdown的小用法
• 博客搭建教程
© 2025 Q-同學
由 Hexo 强力驱动 v3.9.0
|
主题 — NexT.Gemini v6.2.0