Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.03.2016, 16:43   #1
evgenybal
 
Регистрация: 09.04.2015
Сообщений: 9
По умолчанию Оптимизация программы на Си

Условие:
Дана последовательность из N (1 ≤ N ≤ 100000) целых чисел и число K (|K| ≤ 100000). Сдвинуть всю последовательность (сдвиг - циклический) на |K| элементов вправо, если K – положительное и влево, если отрицательное.

Входные данные
В первой строке дано натуральное число N, во второй строке N целых чисел, а в последней целое число K. Все числа во входных данных не превышают 109.

Выходные данные
Требуется вывести полученную последовательность.

Примеры
входные данные
5
5 3 7 4 6
3
выходные данные
7 4 6 5 3

Код:
#include <stdio.h>

int main()
{
	int  k, i, j, n, tmp;
	scanf("%i", &n);
	int x[n];

	for (i = 0; i < n; i++)//вывод массива
	{
		scanf("%i", &x[i]);
	}

	scanf("%i", &k);
	if (k > 0)
	for (j = 0; j < k; j++)
		{
			for (i = n - 1; i > 0; i--)//принцип: перестановка последнего элемента на первое, путем простой перестановки. Кол-во перестановок зависит от числа k
			{
				tmp = x[i];
				x[i] = x[i - 1];
				x[i - 1] = tmp;

			}
		}
	else 
	for (j = 0; j < -k; j++)
		{
			for (i = 0; i < n-1; i++)
			{
				tmp = x[i];
				x[i] = x[i + 1];
				x[i + 1] = tmp;

			}
		}
	
	for (i = 0; i < n; i++) printf("%i ", x[i]);
	return 0;


}
Задачка взята с сайта, с поддержкой автоматической проверки кода путем серии тестов. Часть тестов программа не проходит, так как Превышено максимальное время работы. Вопрос: в чем может быть причина, так как я понимаю что мой код далек от идеала по краткости
evgenybal вне форума Ответить с цитированием
Старый 14.03.2016, 17:53   #2
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,316
По умолчанию

Если реальный сдвиг производить не нужно, то после считывания всех данных можно вывести ответ:
Код:
i = k = (n - k % n) % n;
do {
    printf("%i ", x[i]);
    i = (i + 1) % n;
} while (i != k);
Проблема не в краткости кода, а в его временной сложности. Вы делаете K простых сдвигов, хотя можно или сразу вывести ответ, или произвести сразу сдвиг на К через дополнительный массив.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )

Последний раз редактировалось BDA; 14.03.2016 в 17:55.
BDA вне форума Ответить с цитированием
Старый 14.03.2016, 21:26   #3
max_prorok
Форумчанин
 
Регистрация: 06.10.2011
Сообщений: 181
По умолчанию

Возможно будет хуже и медленней, а может через связные списки будет быстрее работать?
max_prorok вне форума Ответить с цитированием
Старый 14.03.2016, 23:48   #4
evgenybal
 
Регистрация: 09.04.2015
Сообщений: 9
По умолчанию

Цитата:
Сообщение от BDA Посмотреть сообщение
Если реальный сдвиг производить не нужно, то после считывания всех данных можно вывести ответ:
Код:
i = k = (n - k % n) % n;
do {
    printf("%i ", x[i]);
    i = (i + 1) % n;
} while (i != k);
Проблема не в краткости кода, а в его временной сложности. Вы делаете K простых сдвигов, хотя можно или сразу вывести ответ, или произвести сразу сдвиг на К через дополнительный массив.
Честно? код шикарный. Сам бы наверное не додумался. Однако никак не могу осознать эту строчку: i = k = (n - k % n) % n;
evgenybal вне форума Ответить с цитированием
Старый 15.03.2016, 00:05   #5
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,316
По умолчанию

Имеем желаемый сдвиг K. Если K больше N, то каждые N сдвигов массив будет возвращаться в исходное положение, так что сразу рассмотрим только сдвиг на K%N. Сдвиг в одну сторону на K аналогичен сдвигу в другую сторону на N-K. Поэтому рассматриваю сдвиг N+K%N. Этот сдвиг опять может быть больше N, так что (N+K%N)%N. Поскольку я только вывожу массив с определенного места, то мне нужно найти место, с которого выводить массив. Если сдвиг производится вправо, то место вывода левее начала массива и наоборот, поэтому формула (N-K%N)%N.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Старый 15.03.2016, 15:09   #6
max_prorok
Форумчанин
 
Регистрация: 06.10.2011
Сообщений: 181
По умолчанию

Цитата:
Сообщение от max_prorok Посмотреть сообщение
Возможно будет хуже и медленней, а может через связные списки будет быстрее работать?
Не слушайте меня. Вру я. Остапа понесло...
max_prorok вне форума Ответить с цитированием
Старый 15.03.2016, 15:17   #7
max_prorok
Форумчанин
 
Регистрация: 06.10.2011
Сообщений: 181
По умолчанию

Но есть задумка, по поводу того, как использовать два массива. Если конечно условия позволяют.
Один массив содержит элементы, которые даются по заданию. Второй хранит в себе номера элементов первого массива. И когда ты сдвигаешь элементы вправо или влево, сам массив ты не трогаешь, а лишь поэлементно добавляешь число сдвигов во второй массив. Ну и конечно же, если сумма превышает число элементов первого массива, то просто откидывать количество элементов массива.
По идее должно работать быстрее, чем приведенный вами код, но не факт, что быстрее чем код приведенный BDA.
max_prorok вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Оптимизация программы vladis222 Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 3 14.11.2013 13:49
Оптимизация программы на С++ programka311 Помощь студентам 10 21.03.2013 14:29
Оптимизация программы danil123 Общие вопросы Delphi 8 20.01.2013 19:34
Оптимизация программы Семоха Валерий Помощь студентам 1 26.05.2012 14:04
оптимизация программы Arsenx777 Работа с сетью в Delphi 1 28.08.2011 14:00