Longest Arithmetic Sequence - Question 1

本文介绍了一种求解数组中最长等差数列的方法。通过构建哈希表存储数列差值及其位置关系,实现了高效查找。示例代码展示了算法实现细节。

Question 1: Given an array, please get the length of the longest arithmetic sequence. The element order in the arithmetic sequence should be same as the element order in the array. For example, in the array {1, 6, 3, 5, 9, 7}, the longest arithmetic sequence is 1, 3, 5, and 7, whose elements have same order as they are in the array, and the length is 4.

参考: http://codercareer.blogspot.com/2014/03/no-53-longest-arithmetic-sequence.html

最妙的是如何计算等差数列长度。请看参考链接,确实是很妙啊!

/* Copyleft: Ming Lin <minggr@gmail.com> */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct pair {
	int diff;
	int i, j;
	struct pair *next;
};

struct pair_list {
	int diff;
	struct pair *head;
	struct pair *tail;
	struct pair_list *chain;
};

struct hash {
	struct pair_list **head;
	int size;
};

struct hash *init_hash(int n)
{
	struct hash *h;
	struct pair_list **p;
	int size;

	h = malloc(sizeof(*h));
	size = n*sizeof(struct pair_list *);
	p = malloc(size);
	memset(p, 0, size);
	h->head = p;
	h->size = n;

	return h;
}

int hash_index(struct hash *h, int key)
{
	if (key < 0)
		key = -key;
	return key % h->size;
}

int mycount = 0;
void pair_add(struct pair_list **head, struct pair *p)
{
	struct pair_list *pl, *prev_pl;

	if (!*head) {
		pl = malloc(sizeof(struct pair_list));
		pl->diff = p->diff;
		pl->head = pl->tail = p;
		pl->chain = NULL;
		*head = pl;
		return;
	}

	pl = prev_pl = *head;

	while (pl && pl->diff != p->diff) {
		prev_pl = pl;
		pl = pl->chain;
	}

	if (pl) {
		pl->tail->next = p;
		pl->tail = p;
	} else {
		pl = malloc(sizeof(struct pair_list));
		pl->diff = p->diff;
		pl->head = pl->tail = p;
		pl->chain = NULL;
		prev_pl->chain = pl;
	}
}

void hash_add_pair(struct hash *h, struct pair *p) {
	int i;

	i = hash_index(h, p->diff);
	mycount++;
	pair_add(&h->head[i], p);
}

void hash_add(struct hash *h, int diff, int i, int j)
{
	struct pair *p;

	p = malloc(sizeof(struct pair));
	p->diff = diff;
	p->i = i;
	p->j = j;
	p->next = NULL;

	hash_add_pair(h, p);
}

void hash_build(struct hash *h, int data[], int n)
{
	int i, j;

	for (i = 0; i < n; i++) {
		for (j = i + 1; j < n; j++) {
			hash_add(h, data[j]-data[i], i, j);
		}
	}
}

void pair_list_dump_one(int *data, struct pair_list *pl)
{
	struct pair *p;

	p = pl->head;
	printf("  diff %d: ", pl->diff);
	while (p) {
		printf("{%d,%d -> %d,%d} ", p->i, p->j, data[p->i], data[p->j]);		
		p = p->next;
	}
	printf("\n");
}

void pair_list_dump(int *data, struct pair_list *pl)
{
	while (pl) {
		pair_list_dump_one(data, pl);
		pl = pl->chain;
	}	
}

void hash_dump(struct hash *h, int *data)
{
	int i;

	for (i = 0; i < h->size; i++) {
		printf("index %d\n", i);
		pair_list_dump(data, h->head[i]);
	}
}

int pair_list_len_one(struct pair_list *pl, int *len, int n)
{
	struct pair *p;
	int max = 0;

	while (n >= 1) {
		n--;	
		len[n] = 1;
	}

	p = pl->head;
	while (p) {
		len[p->j] = len[p->i] + 1;
		if (len[p->j] > max)
			max = len[p->j];
		p = p->next;
	}

	return max;
}

int pair_list_len(struct pair_list *pl, int *len, int n)
{
	int max = 0;

	while (pl) {
		int tmp = pair_list_len_one(pl, len, n);
		if (tmp > max)
			max = tmp;
		pl = pl->chain;
	}

	return max;
}

int length_of_longest_arithmetic_sequence(struct hash *h)
{
	int *len;
	int max = 0;
	int i;

	len = malloc(h->size * sizeof(int));
	for (i = 0; i < h->size; i++) {
		int tmp = 0;

		if (h->head[i])
			tmp = pair_list_len(h->head[i], len, h->size);
		if (tmp > max)
			max = tmp;
	}

	return max;
}

int main()
{
	struct hash *h;
	//int data[] = {1, 6, 3, 5, 9, 7};
	//int n = 6;
	int data[] = { 1, 8, 3, 6, 5, 4, 7, 2, 9 };
	int n = 9;

	h = init_hash(n);
	hash_build(h, data, n);
	hash_dump(h, data);
	printf("length_of_longest_arithmetic_sequence=%d\n", length_of_longest_arithmetic_sequence(h));

	return 0;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值